Skip to content

Commit b3e9a69

Browse files
authored
add AES256 cypher decryption to support FIPS 140-3 (#2101)
* fips changes * cleanup * Update HandlerUtil
1 parent b78697c commit b3e9a69

2 files changed

Lines changed: 54 additions & 19 deletions

File tree

AzureMonitorAgent/agent.py

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2888,19 +2888,32 @@ def get_settings():
28882888
'{0}.prv'.format(
28892889
settings_thumbprint))
28902890
decoded_settings = base64.standard_b64decode(encoded_settings)
2891-
decrypt_cmd = 'openssl smime -inform DER -decrypt -recip {0} ' \
2892-
'-inkey {1}'.format(encoded_cert_path,
2893-
encoded_key_path)
28942891

2895-
try:
2896-
session = subprocess.Popen([decrypt_cmd], shell = True,
2897-
stdin = subprocess.PIPE,
2898-
stderr = subprocess.STDOUT,
2899-
stdout = subprocess.PIPE)
2900-
output = session.communicate(decoded_settings)
2901-
except OSError:
2902-
pass
2903-
protected_settings_str = output[0]
2892+
2893+
# FIPS 140-3: use 'openssl cms' (supports AES256 & DES_EDE3_CBC) with fallback to legacy 'openssl smime'
2894+
cms_cmd = 'openssl cms -inform DER -decrypt -recip {0} -inkey {1}'.format(encoded_cert_path, encoded_key_path)
2895+
smime_cmd = 'openssl smime -inform DER -decrypt -recip {0} -inkey {1}'.format(encoded_cert_path, encoded_key_path)
2896+
2897+
protected_settings_str = None
2898+
for decrypt_cmd in [cms_cmd, smime_cmd]:
2899+
try:
2900+
session = subprocess.Popen([decrypt_cmd], shell=True,
2901+
stdin=subprocess.PIPE,
2902+
stderr=subprocess.STDOUT,
2903+
stdout=subprocess.PIPE)
2904+
output = session.communicate(decoded_settings)
2905+
# success only if return code is 0 and we have output
2906+
if session.returncode == 0 and output[0]:
2907+
protected_settings_str = output[0]
2908+
if decrypt_cmd == cms_cmd:
2909+
hutil_log_info('Decrypted protectedSettings using openssl cms.')
2910+
else:
2911+
hutil_log_info('Decrypted protectedSettings using openssl smime fallback.')
2912+
break
2913+
else:
2914+
hutil_log_info('Attempt to decrypt protectedSettings with "{0}" failed (rc={1}).'.format(decrypt_cmd, session.returncode))
2915+
except OSError:
2916+
pass
29042917

29052918
if protected_settings_str is None:
29062919
log_and_exit('Enable', GenericErrorCode, 'Failed decrypting protectedSettings')

Utils/HandlerUtil.py

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import json
5959
import time
6060
import re
61+
import subprocess
6162
# imp was deprecated in python 3.12
6263
if sys.version_info >= (3, 12):
6364
import importlib
@@ -195,16 +196,37 @@ def _parse_config(self, ctxt):
195196
cert = waagent.LibDir + '/' + thumb + '.crt'
196197
pkey = waagent.LibDir + '/' + thumb + '.prv'
197198
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+
203225
jctxt = ''
204226
try:
205-
jctxt = json.loads(cleartxt)
227+
jctxt = json.loads(protected_settings_str)
206228
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))
208230
handlerSettings['protectedSettings']=jctxt
209231
self.log('Config decoded correctly.')
210232
return config

0 commit comments

Comments
 (0)