Loading CHANGES +4 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,10 @@ OID NID. [Steve Henson] *) New chain verification flags for Suite B levels of security. Check algorithms are acceptable when flags are set in X509_verify_cert. [Steve Henson] *) Make tls1_check_chain return a set of flags indicating checks passed by a certificate chain. Add additional tests to handle client certificates: checks for matching certificate type and issuer name Loading crypto/x509/x509.h +5 −0 Original line number Diff line number Diff line Loading @@ -965,6 +965,11 @@ int X509_REVOKED_set_revocationDate(X509_REVOKED *r, ASN1_TIME *tm); int X509_REQ_check_private_key(X509_REQ *x509,EVP_PKEY *pkey); int X509_check_private_key(X509 *x509,EVP_PKEY *pkey); int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain, unsigned long flags); int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags); int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b); unsigned long X509_issuer_and_serial_hash(X509 *a); Loading crypto/x509/x509_cmp.c +124 −0 Original line number Diff line number Diff line Loading @@ -341,3 +341,127 @@ int X509_check_private_key(X509 *x, EVP_PKEY *k) return 1; return 0; } /* Check a suite B algorithm is permitted: pass in a public key and * the NID of its signature (or 0 if no signature). The pflags is * a pointer to a flags field which must contain the suite B verification * flags. */ static int check_suite_b(EVP_PKEY *pkey, int sign_nid, unsigned long *pflags) { const EC_GROUP *grp = NULL; int curve_nid; if (pkey && pkey->type == EVP_PKEY_EC) grp = EC_KEY_get0_group(pkey->pkey.ec); if (!grp) return X509_V_ERR_SUITE_B_INVALID_ALGORITHM; curve_nid = EC_GROUP_get_curve_name(grp); /* Check curve is consistent with LOS */ if (curve_nid == NID_secp384r1) /* P-384 */ { /* Check signature algorithm is consistent with * curve. */ if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA384) return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM; if (!(*pflags & X509_V_FLAG_SUITEB_192_LOS)) return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED; /* If we encounter P-384 we cannot use P-256 later */ *pflags &= ~X509_V_FLAG_SUITEB_128_LOS_ONLY; } else if (curve_nid == NID_X9_62_prime256v1) /* P-256 */ { if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA256) return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM; if (!(*pflags & X509_V_FLAG_SUITEB_128_LOS_ONLY)) return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED; } else return X509_V_ERR_SUITE_B_INVALID_CURVE; return X509_V_OK; } int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain, unsigned long flags) { int rv, i, sign_nid; EVP_PKEY *pk = NULL; unsigned long tflags; if (!(flags & X509_V_FLAG_SUITEB_128_LOS)) return X509_V_OK; tflags = flags; /* If no EE certificate passed in must be first in chain */ if (x == NULL) { x = sk_X509_value(chain, 0); i = 1; } else i = 0; if (X509_get_version(x) != 2) { rv = X509_V_ERR_SUITE_B_INVALID_VERSION; /* Correct error depth */ i = 0; goto end; } pk = X509_get_pubkey(x); /* Check EE key only */ rv = check_suite_b(pk, -1, &tflags); if (rv != X509_V_OK) { /* Correct error depth */ i = 0; goto end; } for(; i < sk_X509_num(chain); i++) { sign_nid = X509_get_signature_nid(x); x = sk_X509_value(chain, i); if (X509_get_version(x) != 2) { rv = X509_V_ERR_SUITE_B_INVALID_VERSION; goto end; } EVP_PKEY_free(pk); pk = X509_get_pubkey(x); rv = check_suite_b(pk, sign_nid, &tflags); if (rv != X509_V_OK) goto end; } /* Final check: root CA signature */ rv = check_suite_b(pk, X509_get_signature_nid(x), &tflags); end: if (pk) EVP_PKEY_free(pk); if (rv != X509_V_OK) { /* Invalid signature or LOS errors are for previous cert */ if ((rv == X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM || rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED) && i) i--; /* If we have LOS error and flags changed then we are signing * P-384 with P-256. Use more meaninggul error. */ if (rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED && flags != tflags) rv = X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256; if (perror_depth) *perror_depth = i; } return rv; } int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags) { int sign_nid; if (!(flags & X509_V_FLAG_SUITEB_128_LOS)) return X509_V_OK; sign_nid = OBJ_obj2nid(crl->crl->sig_alg->algorithm); return check_suite_b(pk, sign_nid, &flags); } crypto/x509/x509_txt.c +13 −0 Original line number Diff line number Diff line Loading @@ -184,6 +184,19 @@ const char *X509_verify_cert_error_string(long n) case X509_V_ERR_CRL_PATH_VALIDATION_ERROR: return("CRL path validation error"); case X509_V_ERR_SUITE_B_INVALID_VERSION: return("Suite B: certificate version invalid"); case X509_V_ERR_SUITE_B_INVALID_ALGORITHM: return("Suite B: invalid public key algorithm"); case X509_V_ERR_SUITE_B_INVALID_CURVE: return("Suite B: invalid ECC curve"); case X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM: return("Suite B: invalid signature algorithm"); case X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED: return("Suite B: curve not allowed for this LOS"); case X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256: return("Suite B: cannot sign P-384 with P-256"); case X509_V_ERR_HOSTNAME_MISMATCH: return("Hostname mismatch"); case X509_V_ERR_EMAIL_MISMATCH: Loading crypto/x509/x509_vfy.c +20 −0 Original line number Diff line number Diff line Loading @@ -408,6 +408,17 @@ int X509_verify_cert(X509_STORE_CTX *ctx) ok = ctx->check_revocation(ctx); if(!ok) goto end; i = X509_chain_check_suiteb(&ctx->error_depth, NULL, ctx->chain, ctx->param->flags); if (i != X509_V_OK) { ctx->error = i; ctx->current_cert = sk_X509_value(ctx->chain, ctx->error_depth); ok = cb(0, ctx); if (!ok) goto end; } /* At this point, we have a chain and need to verify it */ if (ctx->verify != NULL) ok=ctx->verify(ctx); Loading Loading @@ -1529,6 +1540,15 @@ static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl) } else { int rv; rv = X509_CRL_check_suiteb(crl, ikey, ctx->param->flags); if (rv != X509_V_OK) { ctx->error=rv; ok = ctx->verify_cb(0, ctx); if (!ok) goto err; } /* Verify CRL signature */ if(X509_CRL_verify(crl, ikey) <= 0) { Loading Loading
CHANGES +4 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,10 @@ OID NID. [Steve Henson] *) New chain verification flags for Suite B levels of security. Check algorithms are acceptable when flags are set in X509_verify_cert. [Steve Henson] *) Make tls1_check_chain return a set of flags indicating checks passed by a certificate chain. Add additional tests to handle client certificates: checks for matching certificate type and issuer name Loading
crypto/x509/x509.h +5 −0 Original line number Diff line number Diff line Loading @@ -965,6 +965,11 @@ int X509_REVOKED_set_revocationDate(X509_REVOKED *r, ASN1_TIME *tm); int X509_REQ_check_private_key(X509_REQ *x509,EVP_PKEY *pkey); int X509_check_private_key(X509 *x509,EVP_PKEY *pkey); int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain, unsigned long flags); int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags); int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b); unsigned long X509_issuer_and_serial_hash(X509 *a); Loading
crypto/x509/x509_cmp.c +124 −0 Original line number Diff line number Diff line Loading @@ -341,3 +341,127 @@ int X509_check_private_key(X509 *x, EVP_PKEY *k) return 1; return 0; } /* Check a suite B algorithm is permitted: pass in a public key and * the NID of its signature (or 0 if no signature). The pflags is * a pointer to a flags field which must contain the suite B verification * flags. */ static int check_suite_b(EVP_PKEY *pkey, int sign_nid, unsigned long *pflags) { const EC_GROUP *grp = NULL; int curve_nid; if (pkey && pkey->type == EVP_PKEY_EC) grp = EC_KEY_get0_group(pkey->pkey.ec); if (!grp) return X509_V_ERR_SUITE_B_INVALID_ALGORITHM; curve_nid = EC_GROUP_get_curve_name(grp); /* Check curve is consistent with LOS */ if (curve_nid == NID_secp384r1) /* P-384 */ { /* Check signature algorithm is consistent with * curve. */ if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA384) return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM; if (!(*pflags & X509_V_FLAG_SUITEB_192_LOS)) return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED; /* If we encounter P-384 we cannot use P-256 later */ *pflags &= ~X509_V_FLAG_SUITEB_128_LOS_ONLY; } else if (curve_nid == NID_X9_62_prime256v1) /* P-256 */ { if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA256) return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM; if (!(*pflags & X509_V_FLAG_SUITEB_128_LOS_ONLY)) return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED; } else return X509_V_ERR_SUITE_B_INVALID_CURVE; return X509_V_OK; } int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain, unsigned long flags) { int rv, i, sign_nid; EVP_PKEY *pk = NULL; unsigned long tflags; if (!(flags & X509_V_FLAG_SUITEB_128_LOS)) return X509_V_OK; tflags = flags; /* If no EE certificate passed in must be first in chain */ if (x == NULL) { x = sk_X509_value(chain, 0); i = 1; } else i = 0; if (X509_get_version(x) != 2) { rv = X509_V_ERR_SUITE_B_INVALID_VERSION; /* Correct error depth */ i = 0; goto end; } pk = X509_get_pubkey(x); /* Check EE key only */ rv = check_suite_b(pk, -1, &tflags); if (rv != X509_V_OK) { /* Correct error depth */ i = 0; goto end; } for(; i < sk_X509_num(chain); i++) { sign_nid = X509_get_signature_nid(x); x = sk_X509_value(chain, i); if (X509_get_version(x) != 2) { rv = X509_V_ERR_SUITE_B_INVALID_VERSION; goto end; } EVP_PKEY_free(pk); pk = X509_get_pubkey(x); rv = check_suite_b(pk, sign_nid, &tflags); if (rv != X509_V_OK) goto end; } /* Final check: root CA signature */ rv = check_suite_b(pk, X509_get_signature_nid(x), &tflags); end: if (pk) EVP_PKEY_free(pk); if (rv != X509_V_OK) { /* Invalid signature or LOS errors are for previous cert */ if ((rv == X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM || rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED) && i) i--; /* If we have LOS error and flags changed then we are signing * P-384 with P-256. Use more meaninggul error. */ if (rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED && flags != tflags) rv = X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256; if (perror_depth) *perror_depth = i; } return rv; } int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags) { int sign_nid; if (!(flags & X509_V_FLAG_SUITEB_128_LOS)) return X509_V_OK; sign_nid = OBJ_obj2nid(crl->crl->sig_alg->algorithm); return check_suite_b(pk, sign_nid, &flags); }
crypto/x509/x509_txt.c +13 −0 Original line number Diff line number Diff line Loading @@ -184,6 +184,19 @@ const char *X509_verify_cert_error_string(long n) case X509_V_ERR_CRL_PATH_VALIDATION_ERROR: return("CRL path validation error"); case X509_V_ERR_SUITE_B_INVALID_VERSION: return("Suite B: certificate version invalid"); case X509_V_ERR_SUITE_B_INVALID_ALGORITHM: return("Suite B: invalid public key algorithm"); case X509_V_ERR_SUITE_B_INVALID_CURVE: return("Suite B: invalid ECC curve"); case X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM: return("Suite B: invalid signature algorithm"); case X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED: return("Suite B: curve not allowed for this LOS"); case X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256: return("Suite B: cannot sign P-384 with P-256"); case X509_V_ERR_HOSTNAME_MISMATCH: return("Hostname mismatch"); case X509_V_ERR_EMAIL_MISMATCH: Loading
crypto/x509/x509_vfy.c +20 −0 Original line number Diff line number Diff line Loading @@ -408,6 +408,17 @@ int X509_verify_cert(X509_STORE_CTX *ctx) ok = ctx->check_revocation(ctx); if(!ok) goto end; i = X509_chain_check_suiteb(&ctx->error_depth, NULL, ctx->chain, ctx->param->flags); if (i != X509_V_OK) { ctx->error = i; ctx->current_cert = sk_X509_value(ctx->chain, ctx->error_depth); ok = cb(0, ctx); if (!ok) goto end; } /* At this point, we have a chain and need to verify it */ if (ctx->verify != NULL) ok=ctx->verify(ctx); Loading Loading @@ -1529,6 +1540,15 @@ static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl) } else { int rv; rv = X509_CRL_check_suiteb(crl, ikey, ctx->param->flags); if (rv != X509_V_OK) { ctx->error=rv; ok = ctx->verify_cb(0, ctx); if (!ok) goto err; } /* Verify CRL signature */ if(X509_CRL_verify(crl, ikey) <= 0) { Loading