Index: libgcrypt-1.10.0/src/fips.c =================================================================== --- libgcrypt-1.10.0.orig/src/fips.c +++ libgcrypt-1.10.0/src/fips.c @@ -36,6 +36,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. */ @@ -386,6 +387,77 @@ _gcry_fips_indicator_kdf (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} + }; + +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; + const char *curve_name; + + switch (alg) + { + case GCRY_PK_RSA: + case GCRY_PK_RSA_E: + case GCRY_PK_RSA_S: + oper = va_arg (arg_ptr, enum pk_operation); + switch (oper) + { + case PUBKEY_OP_ENCRYPT: + case PUBKEY_OP_DECRYPT: + return GPG_ERR_NOT_SUPPORTED; + default: + 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; + } } Index: libgcrypt-1.10.0/src/gcrypt.h.in =================================================================== --- libgcrypt-1.10.0.orig/src/gcrypt.h.in +++ libgcrypt-1.10.0/src/gcrypt.h.in @@ -330,7 +330,8 @@ enum gcry_ctl_cmds GCRYCTL_SET_DECRYPTION_TAG = 80, GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER = 81, GCRYCTL_FIPS_SERVICE_INDICATOR_KDF = 82, - GCRYCTL_NO_FIPS_MODE = 83 + GCRYCTL_NO_FIPS_MODE = 83, + GCRYCTL_FIPS_SERVICE_INDICATOR_PK = 84 }; /* Perform various operations defined by CMD. */ Index: libgcrypt-1.10.0/doc/gcrypt.texi =================================================================== --- libgcrypt-1.10.0.orig/doc/gcrypt.texi +++ libgcrypt-1.10.0/doc/gcrypt.texi @@ -987,6 +987,18 @@ certification. If the KDF is approved, t @code{GPG_ERR_NO_ERROR}. Otherwise @code{GPG_ERR_NOT_SUPPORTED} is returned. +@item GCRYCTL_FIPS_SERVICE_INDICATOR_PK; Arguments: enum gcry_pk_algos +[, enum pk_operation (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, an additional parameter for the +operation mode @code{enum pk_operation} is required. For GCRY_PK_ECC, +GCRY_PK_ECDH and GCRY_PK_ECDSA, the additional parameter is 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. + @end table @end deftypefun Index: libgcrypt-1.10.0/src/g10lib.h =================================================================== --- libgcrypt-1.10.0.orig/src/g10lib.h +++ libgcrypt-1.10.0/src/g10lib.h @@ -457,6 +457,7 @@ void _gcry_fips_signal_error (const char int _gcry_fips_indicator_cipher (va_list arg_ptr); int _gcry_fips_indicator_kdf (va_list arg_ptr); +int _gcry_fips_indicator_pk (va_list arg_ptr); int _gcry_fips_is_operational (void); Index: libgcrypt-1.10.0/src/global.c =================================================================== --- libgcrypt-1.10.0.orig/src/global.c +++ libgcrypt-1.10.0/src/global.c @@ -797,6 +797,15 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, rc = _gcry_fips_indicator_kdf (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;