add suite B chain validation flags and associated verify errors
This commit is contained in:
parent
6dbb6219e7
commit
3ad344a517
7 changed files with 184 additions and 0 deletions
4
CHANGES
4
CHANGES
|
@ -4,6 +4,10 @@
|
|||
|
||||
Changes between 1.0.1 and 1.1.0 [xx XXX xxxx]
|
||||
|
||||
*) 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
|
||||
|
|
|
@ -2376,6 +2376,12 @@ int args_verify(char ***pargs, int *pargc,
|
|||
flags |= X509_V_FLAG_CHECK_SS_SIGNATURE;
|
||||
else if (!strcmp(arg, "-trusted_first"))
|
||||
flags |= X509_V_FLAG_TRUSTED_FIRST;
|
||||
else if (!strcmp(arg, "-suiteB_128_only"))
|
||||
flags |= X509_V_FLAG_SUITEB_128_LOS_ONLY;
|
||||
else if (!strcmp(arg, "-suiteB_128"))
|
||||
flags |= X509_V_FLAG_SUITEB_128_LOS;
|
||||
else if (!strcmp(arg, "-suiteB_192"))
|
||||
flags |= X509_V_FLAG_SUITEB_192_LOS;
|
||||
else
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -966,6 +966,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_check_suiteb_chain(int *perror_depth,
|
||||
X509 *x, STACK_OF(X509) *chain,
|
||||
unsigned long flags);
|
||||
int X509_check_suiteb_crl(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);
|
||||
|
|
|
@ -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_check_suiteb_chain(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_check_suiteb_crl(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);
|
||||
}
|
||||
|
||||
|
|
|
@ -185,6 +185,18 @@ const char *X509_verify_cert_error_string(long n)
|
|||
return("CRL path validation error");
|
||||
case X509_V_ERR_PATH_LOOP:
|
||||
return("Path Loop");
|
||||
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");
|
||||
|
||||
default:
|
||||
BIO_snprintf(buf,sizeof buf,"error number %ld",n);
|
||||
|
|
|
@ -387,6 +387,17 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
|
|||
ok = ctx->check_revocation(ctx);
|
||||
if(!ok) goto end;
|
||||
|
||||
i = X509_check_suiteb_chain(&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);
|
||||
|
@ -1474,6 +1485,15 @@ static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl)
|
|||
}
|
||||
else
|
||||
{
|
||||
int rv;
|
||||
rv = X509_check_suiteb_crl(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)
|
||||
{
|
||||
|
|
|
@ -355,6 +355,13 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
|
|||
#define X509_V_ERR_CRL_PATH_VALIDATION_ERROR 54
|
||||
/* Another issuer check debug option */
|
||||
#define X509_V_ERR_PATH_LOOP 55
|
||||
/* Suite B mode algorithm violation */
|
||||
#define X509_V_ERR_SUITE_B_INVALID_VERSION 56
|
||||
#define X509_V_ERR_SUITE_B_INVALID_ALGORITHM 57
|
||||
#define X509_V_ERR_SUITE_B_INVALID_CURVE 58
|
||||
#define X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM 59
|
||||
#define X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED 60
|
||||
#define X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 61
|
||||
|
||||
/* The application is not happy */
|
||||
#define X509_V_ERR_APPLICATION_VERIFICATION 50
|
||||
|
@ -393,6 +400,12 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
|
|||
#define X509_V_FLAG_CHECK_SS_SIGNATURE 0x4000
|
||||
/* Use trusted store first */
|
||||
#define X509_V_FLAG_TRUSTED_FIRST 0x8000
|
||||
/* Suite B 128 bit only mode: not normally used */
|
||||
#define X509_V_FLAG_SUITEB_128_LOS_ONLY 0x10000
|
||||
/* Suite B 192 bit only mode */
|
||||
#define X509_V_FLAG_SUITEB_192_LOS 0x20000
|
||||
/* Suite B 128 bit mode allowing 192 bit algorithms */
|
||||
#define X509_V_FLAG_SUITEB_128_LOS 0x30000
|
||||
|
||||
|
||||
#define X509_VP_FLAG_DEFAULT 0x1
|
||||
|
|
Loading…
Reference in a new issue