|
58 | 58 | import json |
59 | 59 | import time |
60 | 60 | import re |
| 61 | +import subprocess |
61 | 62 | # imp was deprecated in python 3.12 |
62 | 63 | if sys.version_info >= (3, 12): |
63 | 64 | import importlib |
@@ -195,16 +196,37 @@ def _parse_config(self, ctxt): |
195 | 196 | cert = waagent.LibDir + '/' + thumb + '.crt' |
196 | 197 | pkey = waagent.LibDir + '/' + thumb + '.prv' |
197 | 198 | unencodedSettings = base64.standard_b64decode(protectedSettings) |
198 | | - openSSLcmd = "openssl smime -inform DER -decrypt -recip {0} -inkey {1}" |
199 | | - cleartxt = waagent.RunSendStdin(openSSLcmd.format(cert, pkey), unencodedSettings)[1] |
200 | | - if cleartxt is None: |
201 | | - self.error("OpenSSL decode error using thumbprint " + thumb) |
202 | | - self.do_exit(1, "Enable", 'error', '1', 'Failed to decrypt protectedSettings') |
| 199 | + |
| 200 | + # FIPS 140-3: use 'openssl cms' (supports AES256 & DES_EDE3_CBC) with fallback to legacy 'openssl smime' |
| 201 | + cms_cmd = 'openssl cms -inform DER -decrypt -recip {0} -inkey {1}'.format(cert,pkey) |
| 202 | + smime_cmd = 'openssl smime -inform DER -decrypt -recip {0} -inkey {1}'.format(cert,pkey) |
| 203 | + |
| 204 | + protected_settings_str = None |
| 205 | + for decrypt_cmd in [cms_cmd, smime_cmd]: |
| 206 | + try: |
| 207 | + session = subprocess.Popen([decrypt_cmd], shell=True, |
| 208 | + stdin=subprocess.PIPE, |
| 209 | + stderr=subprocess.STDOUT, |
| 210 | + stdout=subprocess.PIPE) |
| 211 | + output = session.communicate(unencodedSettings) |
| 212 | + # success only if return code is 0 and we have output |
| 213 | + if session.returncode == 0 and output[0]: |
| 214 | + protected_settings_str = output[0] |
| 215 | + if decrypt_cmd == cms_cmd: |
| 216 | + self.log('Decrypted protectedSettings using openssl cms.') |
| 217 | + else: |
| 218 | + self.log('Decrypted protectedSettings using openssl smime fallback.') |
| 219 | + break |
| 220 | + else: |
| 221 | + self.log('Attempt to decrypt protectedSettings with "{0}" failed (rc={1}).'.format(decrypt_cmd, session.returncode)) |
| 222 | + except OSError: |
| 223 | + pass |
| 224 | + |
203 | 225 | jctxt = '' |
204 | 226 | try: |
205 | | - jctxt = json.loads(cleartxt) |
| 227 | + jctxt = json.loads(protected_settings_str) |
206 | 228 | except: |
207 | | - self.error('JSON exception decoding ' + HandlerUtility.redact_protected_settings(cleartxt)) |
| 229 | + self.error('JSON exception decoding ' + HandlerUtility.redact_protected_settings(protected_settings_str)) |
208 | 230 | handlerSettings['protectedSettings']=jctxt |
209 | 231 | self.log('Config decoded correctly.') |
210 | 232 | return config |
|
0 commit comments