# HG changeset patch # User John Dennis # Date 1434146324 14400 # Fri Jun 12 17:58:44 2015 -0400 # Node ID 6096d0660e2abefcee12e502fed029663d435c54 # Parent a5e07e90e9c8cb08c5fb46eba16bdb43b94d67c3 Some unit tests fail in FIPS mode Resolves bug https://bugzilla.redhat.com/show_bug.cgi?id=1194349 Essentially there were 2 problems: 1. The DB password 'db_passwd' was not complex enough for FIPS changing it to 'DB_passwd' with upper case was sufficient. Also changed the pkcs password 'pk12_passwd' to 'PK12_passwd' 2. NSS adds a random salt in FIPS mode for the PKCS12 operations. The presence of this salt was causing a comparision to fail, the exact salt is insignificant to the operation of the test so it was stripped out prior to comparision. At the same time setup_certs.py was augmented to accept a --fips parameter to put the DB into fips mode and setup_certs.py also now reports the status of the system FIPS mode and DB FIPS mode in addtion to the existing info displayed at its conclusion. diff --git a/test/setup_certs.py b/test/setup_certs.py --- a/test/setup_certs.py +++ b/test/setup_certs.py @@ -4,6 +4,7 @@ import atexit import logging import os +import re import shutil import subprocess import sys @@ -11,6 +12,12 @@ import tempfile #------------------------------------------------------------------------------- +logger = None + +FIPS_SWITCH_FAILED_ERR = 11 +FIPS_ALREADY_ON_ERR = 12 +FIPS_ALREADY_OFF_ERR = 13 + class CmdError(Exception): def __init__(self, cmd_args, returncode, message=None, stdout=None, stderr=None): @@ -41,7 +48,7 @@ returncode = p.returncode if returncode != 0: raise CmdError(cmd_args, returncode, - 'failed %s' % (', '.join(cmd_args)), + 'failed %s' % (' '.join(cmd_args)), stdout, stderr) return stdout, stderr except OSError as e: @@ -319,9 +326,75 @@ run_cmd(cmd_args) return name +def parse_fips_enabled(string): + if re.search('FIPS mode disabled', string): + return False + if re.search('FIPS mode enabled', string): + return True + raise ValueError('unknown fips enabled string: "%s"' % string) + +def get_system_fips_enabled(): + fips_path = '/proc/sys/crypto/fips_enabled' + + try: + with open(fips_path) as f: + data = f.read() + except Exception as e: + logger.warning("Unable to determine system FIPS mode: %s" % e) + data = '0' + + value = int(data) + if value: + return True + else: + return False + + +def get_db_fips_enabled(db_name): + cmd_args = ['/usr/bin/modutil', + '-dbdir', db_name, # NSS database + '-chkfips', 'true', # enable/disable fips + ] + + try: + stdout, stderr = run_cmd(cmd_args) + return parse_fips_enabled(stdout) + except CmdError as e: + if e.returncode == FIPS_SWITCH_FAILED_ERR: + return parse_fips_enabled(e.stdout) + else: + raise + +def set_fips_mode(options): + if options.fips: + state = 'true' + else: + if get_system_fips_enabled(): + logger.warning("System FIPS enabled, cannot disable FIPS") + return + state = 'false' + + logging.info('setting fips: %s', state) + + cmd_args = ['/usr/bin/modutil', + '-dbdir', options.db_name, # NSS database + '-fips', state, # enable/disable fips + '-force' + ] + + try: + stdout, stderr = run_cmd(cmd_args) + except CmdError as e: + if options.fips and e.returncode == FIPS_ALREADY_ON_ERR: + pass + elif not options.fips and e.returncode == FIPS_ALREADY_OFF_ERR: + pass + else: + raise #------------------------------------------------------------------------------- def setup_certs(args): + global logger # --- cmd --- parser = argparse.ArgumentParser(description='create certs for testing', @@ -393,6 +466,9 @@ parser.add_argument('--serial-file', dest='serial_file', help='name of file used to track next serial number') + parser.add_argument('--db-fips', action='store_true', + help='enable FIPS mode on NSS Database') + parser.set_defaults(verbose = False, debug = False, quiet = False, @@ -402,7 +478,7 @@ hostname = os.uname()[1], db_type = 'sql', db_dir = 'pki', - db_passwd = 'db_passwd', + db_passwd = 'DB_passwd', ca_subject = 'CN=Test CA', ca_nickname = 'test_ca', server_subject = 'CN=${hostname}', @@ -416,6 +492,7 @@ valid_months = 12, ca_path_len = 2, serial_file = '${db_dir}/serial', + fips = False, ) @@ -468,6 +545,7 @@ try: create_database(options) + set_fips_mode(options) cert_nicknames.append(create_ca_cert(options)) cert_nicknames.append(create_server_cert(options)) cert_nicknames.append(create_client_cert(options)) @@ -488,6 +566,8 @@ logging.info('---------- Summary ----------') logging.info('NSS database name="%s", password="%s"', options.db_name, options.db_passwd) + logging.info('system FIPS mode=%s', get_system_fips_enabled()); + logging.info('DB FIPS mode=%s', get_db_fips_enabled(options.db_name)); logging.info('CA nickname="%s", CA subject="%s"', options.ca_nickname, options.ca_subject) logging.info('server nickname="%s", server subject="%s"', diff --git a/test/test_client_server.py b/test/test_client_server.py --- a/test/test_client_server.py +++ b/test/test_client_server.py @@ -22,7 +22,7 @@ verbose = False info = False -password = 'db_passwd' +password = 'DB_passwd' use_ssl = True client_cert_action = NO_CLIENT_CERT db_name = 'sql:pki' diff --git a/test/test_pkcs12.py b/test/test_pkcs12.py --- a/test/test_pkcs12.py +++ b/test/test_pkcs12.py @@ -15,8 +15,8 @@ verbose = False db_name = 'sql:pki' -db_passwd = 'db_passwd' -pk12_passwd = 'pk12_passwd' +db_passwd = 'DB_passwd' +pk12_passwd = 'PK12_passwd' cert_nickname = 'test_user' pk12_filename = '%s.p12' % cert_nickname @@ -115,6 +115,9 @@ raise ValueError('Could not file Key section in pk12 listing') return text[match.start(0):] +def strip_salt_from_pk12_listing(text): + return re.sub(r'\s+Salt:\s*\n.*', '', text) + #------------------------------------------------------------------------------- def load_tests(loader, tests, pattern): @@ -206,9 +209,11 @@ pk12_listing = list_pk12(pk12_filename) pk12_listing = strip_key_from_pk12_listing(pk12_listing) + pk12_listing = strip_salt_from_pk12_listing(pk12_listing) exported_pk12_listing = list_pk12(exported_pk12_filename) exported_pk12_listing = strip_key_from_pk12_listing(exported_pk12_listing) + exported_pk12_listing = strip_salt_from_pk12_listing(exported_pk12_listing) self.assertEqual(pk12_listing, exported_pk12_listing)