Index: libgcrypt-1.10.2/src/fips.c =================================================================== --- libgcrypt-1.10.2.orig/src/fips.c +++ libgcrypt-1.10.2/src/fips.c @@ -38,6 +38,7 @@ #include "g10lib.h" #include "cipher-proto.h" +#include "cipher.h" #include "../random/random.h" /* The states of the finite state machine used in fips mode. */ @@ -399,6 +400,94 @@ _gcry_fips_indicator_mac (va_list arg_pt default: return GPG_ERR_NOT_SUPPORTED; } +} + +/* FIPS approved curves, extracted from: + * cipher/ecc-curves.c:curve_aliases[] and domain_parms[]. */ +static const struct +{ + const char *name; /* Our name. */ + const char *other; /* Other name. */ +} fips_approved_curve[] = + { + /* "NIST P-192" is non-approved if FIPS 140-3 */ + /* { "NIST P-192", "1.2.840.10045.3.1.1" }, /\* X9.62 OID *\/ */ + /* { "NIST P-192", "prime192v1" }, /\* X9.62 name. *\/ */ + /* { "NIST P-192", "secp192r1" }, /\* SECP name. *\/ */ + /* { "NIST P-192", "nistp192" }, /\* rfc5656. *\/ */ + + { "NIST P-224", "secp224r1" }, + { "NIST P-224", "1.3.132.0.33" }, /* SECP OID. */ + { "NIST P-224", "nistp224" }, /* rfc5656. */ + + { "NIST P-256", "1.2.840.10045.3.1.7" }, /* From NIST SP 800-78-1. */ + { "NIST P-256", "prime256v1" }, + { "NIST P-256", "secp256r1" }, + { "NIST P-256", "nistp256" }, /* rfc5656. */ + + { "NIST P-384", "secp384r1" }, + { "NIST P-384", "1.3.132.0.34" }, + { "NIST P-384", "nistp384" }, /* rfc5656. */ + + { "NIST P-521", "secp521r1" }, + { "NIST P-521", "1.3.132.0.35" }, + { "NIST P-521", "nistp521" }, /* rfc5656. */ + { NULL, NULL} + }; + +enum pk_operation convert_from_pk_usage(unsigned int pk_usage) +{ + switch (pk_usage) + { + case GCRY_PK_USAGE_SIGN: + return PUBKEY_OP_SIGN; + case GCRY_PK_USAGE_ENCR: + return PUBKEY_OP_ENCRYPT; + default: + return PUBKEY_OP_DECRYPT; + } +} + +int +_gcry_fips_indicator_pk (va_list arg_ptr) +{ + enum gcry_pk_algos alg = va_arg (arg_ptr, enum gcry_pk_algos); + enum pk_operation oper; + unsigned int keylen; + const char *curve_name; + + switch (alg) + { + case GCRY_PK_RSA: + case GCRY_PK_RSA_E: + case GCRY_PK_RSA_S: + oper = convert_from_pk_usage(va_arg (arg_ptr, unsigned int)); + switch (oper) + { + case PUBKEY_OP_ENCRYPT: + case PUBKEY_OP_DECRYPT: + return GPG_ERR_NOT_SUPPORTED; + default: + keylen = va_arg (arg_ptr, unsigned int); + if (keylen < 2048) + return GPG_ERR_NOT_SUPPORTED; + return GPG_ERR_NO_ERROR; + } + case GCRY_PK_ECC: + case GCRY_PK_ECDH: + case GCRY_PK_ECDSA: + curve_name = va_arg (arg_ptr, const char *); + for (int idx = 0; fips_approved_curve[idx].name; ++idx) + { + /* Check for the usual name and an alias. */ + if (!strcmp (curve_name, fips_approved_curve[idx].name) || + !strcmp (curve_name, fips_approved_curve[idx].other)) + return GPG_ERR_NO_ERROR; + } + return GPG_ERR_NOT_SUPPORTED; + default: + return GPG_ERR_NOT_SUPPORTED; + } } int Index: libgcrypt-1.10.2/src/gcrypt.h.in =================================================================== --- libgcrypt-1.10.2.orig/src/gcrypt.h.in +++ libgcrypt-1.10.2/src/gcrypt.h.in @@ -334,7 +334,8 @@ enum gcry_ctl_cmds GCRYCTL_FIPS_SERVICE_INDICATOR_FUNCTION = 84, GCRYCTL_FIPS_SERVICE_INDICATOR_MAC = 85, GCRYCTL_FIPS_SERVICE_INDICATOR_MD = 86, - GCRYCTL_FIPS_SERVICE_INDICATOR_PK_FLAGS = 87 + GCRYCTL_FIPS_SERVICE_INDICATOR_PK_FLAGS = 87, + GCRYCTL_FIPS_SERVICE_INDICATOR_PK = 88 }; /* Perform various operations defined by CMD. */ Index: libgcrypt-1.10.2/doc/gcrypt.texi =================================================================== --- libgcrypt-1.10.2.orig/doc/gcrypt.texi +++ libgcrypt-1.10.2/doc/gcrypt.texi @@ -997,6 +997,19 @@ Check if the given message digest algori FIPS 140-3 certification. If the algorithm is approved, this function returns @code{GPG_ERR_NO_ERROR}. Otherwise @code{GPG_ERR_NOT_SUPPORTED} is returned. +@item GCRYCTL_FIPS_SERVICE_INDICATOR_PK; Arguments: enum gcry_pk_algos [, constantsGCRY_PK_USAGE_ENCR or GCRY_PK_USAGE_SIGN, unsigned int (only for GCRY_PK_RSA)] [, const char * (only for GCRY_PK_ECC, GCRY_PK_ECDH or GCRY_PK_ECDSA)] + +Check if the given asymmetric cipher is approved under the current +FIPS 140-3 certification. For GCRY_PK_RSA, two additional parameter +are required: first describes the purpose of the algorithm through one +of the constants (GCRY_PK_USAGE_ENCR for encryption or decryption +operations; GCRY_PK_USAGE_SIGN for sign or verify operations). Second +one is the key length. For GCRY_PK_ECC, GCRY_PK_ECDH and +GCRY_PK_ECDSA, only a single parameter is needed: the curve name or +its alias as @code{const char *}. If the combination is approved, this +function returns @code{GPG_ERR_NO_ERROR}. Otherwise +@code{GPG_ERR_NOT_SUPPORTED} is returned. + @item GCRYCTL_FIPS_SERVICE_INDICATOR_PK_FLAGS; Arguments: const char * Check if the given public key operation flag or s-expression object name is Index: libgcrypt-1.10.2/src/g10lib.h =================================================================== --- libgcrypt-1.10.2.orig/src/g10lib.h +++ libgcrypt-1.10.2/src/g10lib.h @@ -460,6 +460,7 @@ int _gcry_fips_indicator_mac (va_list ar int _gcry_fips_indicator_md (va_list arg_ptr); int _gcry_fips_indicator_kdf (va_list arg_ptr); int _gcry_fips_indicator_function (va_list arg_ptr); +int _gcry_fips_indicator_pk (va_list arg_ptr); int _gcry_fips_indicator_pk_flags (va_list arg_ptr); int _gcry_fips_is_operational (void); Index: libgcrypt-1.10.2/src/global.c =================================================================== --- libgcrypt-1.10.2.orig/src/global.c +++ libgcrypt-1.10.2/src/global.c @@ -825,6 +834,15 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, rc = _gcry_fips_indicator_pk_flags (arg_ptr); break; + case GCRYCTL_FIPS_SERVICE_INDICATOR_PK: + /* Get FIPS Service Indicator for a given asymmetric algorithm. For + * GCRY_PK_RSA, an additional parameter for the operation mode is + * required. For ECC, ECDH and ECDSA, the additional parameter is the + * curve name or its alias. Returns GPG_ERR_NO_ERROR if the + * algorithm is allowed or GPG_ERR_NOT_SUPPORTED otherwise. */ + rc = _gcry_fips_indicator_pk (arg_ptr); + break; + case PRIV_CTL_INIT_EXTRNG_TEST: /* Init external random test. */ rc = GPG_ERR_NOT_SUPPORTED; break;