diff options
author | Wyllys Ingersoll <wyllys.ingersoll@sun.com> | 2010-03-22 13:57:47 -0700 |
---|---|---|
committer | Wyllys Ingersoll <wyllys.ingersoll@sun.com> | 2010-03-22 13:57:47 -0700 |
commit | e65e5c2d2f32a99e8c5f740cabae9075dab03ce7 (patch) | |
tree | 09b70c15a705c7de105b96d1c7c0057ebc13b9e5 /usr/src/lib/libkmf | |
parent | c7facc54c4abed9e554ff80225311e6b7048d3c9 (diff) | |
download | illumos-joyent-e65e5c2d2f32a99e8c5f740cabae9075dab03ce7.tar.gz |
PSARC 2010/032 EC and SHA2 for KMF
6902640 pktool/KMF needs to support ECDSA keys and certificates
6787016 pktool can offer the ability to generate RSA keypairs
Diffstat (limited to 'usr/src/lib/libkmf')
18 files changed, 1734 insertions, 1186 deletions
diff --git a/usr/src/lib/libkmf/ber_der/common/clasn1.c b/usr/src/lib/libkmf/ber_der/common/clasn1.c index d6e31390fd..2e1c3400c1 100644 --- a/usr/src/lib/libkmf/ber_der/common/clasn1.c +++ b/usr/src/lib/libkmf/ber_der/common/clasn1.c @@ -1,16 +1,15 @@ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (c) 1995-1999 Intel Corporation. All rights reserved. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <strings.h> #include <kmftypes.h> #include <ber_der.h> +#include <kmfber_int.h> #include <kmfapi.h> #include <kmfapiP.h> @@ -23,14 +22,18 @@ const KMF_OID extension_request_oid = {OID_PKCS_9_LENGTH + 1, OID_ExtensionRequest}; static KMF_RETURN -encode_algoid(BerElement *asn1, KMF_X509_ALGORITHM_IDENTIFIER *algoid) +encode_algoid(BerElement *asn1, KMF_X509_ALGORITHM_IDENTIFIER *algoid, + boolean_t encode_params) { KMF_RETURN ret = KMF_OK; if (kmfber_printf(asn1, "{D", &algoid->algorithm) == -1) { ret = KMF_ERR_BAD_CERT_FORMAT; } - if (algoid->parameters.Data == NULL || + if (!encode_params) { + if (kmfber_printf(asn1, "}") == -1) + return (KMF_ERR_BAD_CERT_FORMAT); + } else if (algoid->parameters.Data == NULL || algoid->parameters.Length == 0) { if (kmfber_printf(asn1, "n}") == -1) return (KMF_ERR_BAD_CERT_FORMAT); @@ -196,31 +199,98 @@ free_decoded_cert(KMF_X509_CERTIFICATE *certptr) } static KMF_RETURN -get_algoid(BerElement *asn1, KMF_X509_ALGORITHM_IDENTIFIER *algoid) +get_sequence_data(BerElement *asn1, BerValue *seqdata) { - KMF_RETURN ret = KMF_OK; - ber_tag_t tag, newtag; + ber_tag_t tag; ber_len_t size; - BerValue AlgOID = {NULL, 0}; tag = kmfber_next_element(asn1, &size, NULL); - if (tag != BER_CONSTRUCTED_SEQUENCE) + if (tag == BER_OBJECT_IDENTIFIER) { + /* The whole block is the OID. */ + size += kmfber_calc_taglen(tag) + kmfber_calc_lenlen(size); + seqdata->bv_val = malloc(size); + if (seqdata->bv_val == NULL) { + return (KMF_ERR_MEMORY); + } + /* read the raw data into the Algoritm params area. */ + if (kmfber_read(asn1, seqdata->bv_val, size) == + -1) { + return (KMF_ERR_BAD_CERT_FORMAT); + } + seqdata->bv_len = size; + return (KMF_OK); + } else if (tag != BER_CONSTRUCTED_SEQUENCE) + return (KMF_ERR_BAD_CERT_FORMAT); + + if ((kmfber_scanf(asn1, "tl", &tag, &size)) == -1) { return (KMF_ERR_BAD_CERT_FORMAT); + } + /* + * We need to read the tag and the length bytes too, + * so adjust the size. + */ + size += kmfber_calc_taglen(tag) + kmfber_calc_lenlen(size); + seqdata->bv_val = malloc(size); + if (seqdata->bv_val == NULL) { + return (KMF_ERR_MEMORY); + } + /* read the raw data into the Algoritm params area. */ + if (kmfber_read(asn1, seqdata->bv_val, size) == + -1) { + return (KMF_ERR_BAD_CERT_FORMAT); + } + seqdata->bv_len = size; + return (KMF_OK); +} + +static KMF_RETURN +get_algoid(BerElement *asn1, KMF_X509_ALGORITHM_IDENTIFIER *algoid) +{ + KMF_RETURN rv = KMF_OK; + ber_tag_t tag; + ber_len_t size; + BerValue algoid_data; + BerValue AlgOID; + BerElement *oidasn1 = NULL; + + /* Read the entire OID seq into it's own data block */ + rv = get_sequence_data(asn1, &algoid_data); + if (rv != KMF_OK) + return (rv); + + /* Now parse just this block so we don't overrun */ + if ((oidasn1 = kmfder_init(&algoid_data)) == NULL) + return (KMF_ERR_MEMORY); + tag = kmfber_next_element(oidasn1, &size, NULL); + if (tag == BER_OBJECT_IDENTIFIER) { + algoid->algorithm.Data = (uchar_t *)algoid_data.bv_val; + algoid->algorithm.Length = algoid_data.bv_len; + algoid->parameters.Data = NULL; + algoid->parameters.Length = 0; + kmfber_free(oidasn1, 1); + return (KMF_OK); + } - if ((tag = kmfber_scanf(asn1, "{Dt", &AlgOID, &newtag)) == -1) { + if ((tag = kmfber_scanf(oidasn1, "{D", &AlgOID)) == -1) { + kmfber_free(oidasn1, 1); return (KMF_ERR_BAD_CERT_FORMAT); } algoid->algorithm.Data = (uchar_t *)AlgOID.bv_val; algoid->algorithm.Length = AlgOID.bv_len; - if (newtag == BER_NULL) { - (void) kmfber_scanf(asn1, "n}"); + tag = kmfber_next_element(oidasn1, &size, NULL); + if (tag == BER_NULL) { + (void) kmfber_scanf(oidasn1, "n}"); + algoid->parameters.Data = NULL; + algoid->parameters.Length = 0; + } else if (tag == KMFBER_END_OF_SEQORSET || tag == KMFBER_DEFAULT) { + /* close sequence, we are done with Algoid */ algoid->parameters.Data = NULL; algoid->parameters.Length = 0; } else { - /* Peek at the tag and length bytes */ - if ((kmfber_scanf(asn1, "tl", &tag, &size)) == -1) { - ret = KMF_ERR_BAD_CERT_FORMAT; + /* The rest of the data is the algorithm parameters */ + if ((kmfber_scanf(oidasn1, "tl", &tag, &size)) == -1) { + rv = KMF_ERR_BAD_CERT_FORMAT; goto cleanup; } @@ -231,26 +301,24 @@ get_algoid(BerElement *asn1, KMF_X509_ALGORITHM_IDENTIFIER *algoid) size += kmfber_calc_taglen(tag) + kmfber_calc_lenlen(size); algoid->parameters.Data = malloc(size); if (algoid->parameters.Data == NULL) { - ret = KMF_ERR_MEMORY; + rv = KMF_ERR_MEMORY; goto cleanup; } /* read the raw data into the Algoritm params area. */ - if (kmfber_read(asn1, (char *)algoid->parameters.Data, + if (kmfber_read(oidasn1, (char *)algoid->parameters.Data, size) == -1) { - ret = KMF_ERR_BAD_CERT_FORMAT; + rv = KMF_ERR_BAD_CERT_FORMAT; goto cleanup; } algoid->parameters.Length = size; - if ((tag = kmfber_scanf(asn1, "}")) == -1) { - ret = KMF_ERR_BAD_CERT_FORMAT; - } } cleanup: - if (ret != KMF_OK) { + if (rv != KMF_OK) { free_algoid(algoid); } + kmfber_free(oidasn1, 1); - return (ret); + return (rv); } static KMF_RETURN @@ -274,7 +342,11 @@ encode_spki(BerElement *asn1, KMF_X509_SPKI *spki) if (kmfber_printf(asn1, "{") == -1) return (KMF_ERR_BAD_CERT_FORMAT); - if ((ret = encode_algoid(asn1, &spki->algorithm)) != KMF_OK) + /* + * The SPKI is the only place where algorithm parameters + * should be encoded. + */ + if ((ret = encode_algoid(asn1, &spki->algorithm, TRUE)) != KMF_OK) return (ret); if (kmfber_printf(asn1, "B}", spki->subjectPublicKey.Data, @@ -346,6 +418,7 @@ cleanup: return (ret); } + KMF_RETURN DerEncodeDSASignature(KMF_DATA *rawdata, KMF_DATA *signature) { @@ -356,7 +429,7 @@ DerEncodeDSASignature(KMF_DATA *rawdata, KMF_DATA *signature) if (rawdata == NULL || signature == NULL) return (KMF_ERR_BAD_PARAMETER); - if (rawdata->Data == NULL || rawdata->Length != DSA_RAW_SIG_LEN) + if (rawdata->Data == NULL || rawdata->Length == 0) return (KMF_ERR_BAD_PARAMETER); asn1 = kmfder_alloc(); @@ -364,10 +437,10 @@ DerEncodeDSASignature(KMF_DATA *rawdata, KMF_DATA *signature) return (KMF_ERR_MEMORY); /* - * The DSA signature is the concatenation of 2 SHA-1 hashed + * The [EC]DSA signature is the concatenation of 2 * bignum values. */ - n = DSA_RAW_SIG_LEN/2; + n = rawdata->Length/2; if (kmfber_printf(asn1, "{II}", rawdata->Data, n, &rawdata->Data[n], n) == -1) { kmfber_free(asn1, 1); @@ -388,12 +461,60 @@ DerEncodeDSASignature(KMF_DATA *rawdata, KMF_DATA *signature) return (KMF_OK); } +/* + * ECDSA and DSA encode signatures the same way. + */ +KMF_RETURN +DerEncodeECDSASignature(KMF_DATA *rawdata, KMF_DATA *signature) +{ + return (DerEncodeDSASignature(rawdata, signature)); +} + +/* + * Convert a signed DSA sig to a fixed-length unsigned one. + * This is necessary because DER encoding seeks to use the + * minimal amount of bytes but we need a full 20 byte DSA + * value with leading 0x00 bytes. + */ +static KMF_RETURN +convert_signed_to_fixed(BerValue *src, BerValue *dst) +{ + int cnt; + char *p; + if (dst->bv_len > src->bv_len) { + cnt = dst->bv_len - src->bv_len; + /* prepend with leading 0s */ + (void) memset(dst->bv_val, 0x00, cnt); + (void) memcpy(dst->bv_val + cnt, src->bv_val, + src->bv_len); + return (KMF_OK); + } + if (dst->bv_len == src->bv_len) { + (void) memcpy(dst->bv_val, src->bv_val, + dst->bv_len); + return (KMF_OK); + } + /* + * src is larger than dest, strip leading 0s. + * This should not be necessary, but do it just in case. + */ + cnt = src->bv_len - dst->bv_len; + p = src->bv_val; + while (cnt-- > 0) { + if (*p++ != 0x00) + return (KMF_ERR_ENCODING); + } + (void) memcpy(dst->bv_val, p, dst->bv_len); + return (KMF_OK); +} + KMF_RETURN DerDecodeDSASignature(KMF_DATA *encoded, KMF_DATA *signature) { KMF_RETURN ret = KMF_OK; BerElement *asn1 = NULL; BerValue buf, *R = NULL, *S = NULL; + BerValue fixedR, fixedS; buf.bv_val = (char *)encoded->Data; buf.bv_len = encoded->Length; @@ -413,14 +534,50 @@ DerDecodeDSASignature(KMF_DATA *encoded, KMF_DATA *signature) goto cleanup; } signature->Length = R->bv_len + S->bv_len; + /* + * If either of the values had a leading 0 lopped off + * they will be 1 byte short and need to be adjusted below. + * The stripping is correct as per ASN.1 rules. + * + * We don't know the exact length that the R and S values + * must be, it depends on the signature algorithm and, + * in the case of EC, the curve used. So instead of + * checking for a specific length, we just check to see + * if the value came out to be an odd number. If so, + * then we know it needs a leading 0x00 byte which + * will be added below when we convert it to a fixed + * length. + */ + if ((R->bv_len % 2) != 0) + signature->Length++; + if ((S->bv_len % 2) != 0) + signature->Length++; + signature->Data = malloc(signature->Length); if (signature->Data == NULL) { ret = KMF_ERR_MEMORY; goto cleanup; } - (void) memcpy(signature->Data, R->bv_val, R->bv_len); - (void) memcpy(&signature->Data[R->bv_len], S->bv_val, S->bv_len); + fixedR.bv_val = (char *)signature->Data; + /* adjust length if it needs a leading 0x00 byte */ + fixedR.bv_len = R->bv_len + (R->bv_len % 2); + + fixedS.bv_val = (char *)(signature->Data + fixedR.bv_len); + /* adjust length if it needs a leading 0x00 byte */ + fixedS.bv_len = S->bv_len + (S->bv_len % 2); + + /* + * This will add back any missing leading 0's + * that were stripped off earlier when the signature + * was parsed. This ensures that the 2 parts of the + * signature are the right length and have the proper + * leading 0's prepended. + */ + ret = convert_signed_to_fixed(R, &fixedR); + if (ret) + goto cleanup; + ret = convert_signed_to_fixed(S, &fixedS); cleanup: if (R && R->bv_val) free(R->bv_val); @@ -436,6 +593,13 @@ cleanup: } KMF_RETURN +DerDecodeECDSASignature(KMF_DATA *encoded, KMF_DATA *signature) +{ + /* ECDSA can be decoded using same code as standard DSA */ + return (DerDecodeDSASignature(encoded, signature)); +} + +KMF_RETURN DerDecodeSPKI(KMF_DATA *EncodedSPKI, KMF_X509_SPKI *spki) { KMF_RETURN ret = KMF_OK; @@ -1472,7 +1636,8 @@ encode_tbs_cert(BerElement *asn1, KMF_X509_TBS_CERT *tbscert) goto cleanup; } - if ((ret = encode_algoid(asn1, &tbscert->signature)) != KMF_OK) + /* Don't encode alg parameters in signature algid area */ + if ((ret = encode_algoid(asn1, &tbscert->signature, FALSE)) != KMF_OK) goto cleanup; /* Encode the Issuer RDN */ @@ -1601,9 +1766,9 @@ DerEncodeSignedCertificate(KMF_X509_CERTIFICATE *signed_cert_ptr, goto cleanup; } - /* Add the Algorithm & Signature Sequence */ + /* Add the Algorithm & Signature Sequence (no parameters) */ if ((ret = encode_algoid(asn1, - &signature->algorithmIdentifier)) != KMF_OK) + &signature->algorithmIdentifier, FALSE)) != KMF_OK) goto cleanup; if (signature->encrypted.Length > 0) { @@ -1721,90 +1886,6 @@ cleanup: return (ret); } -/* - * Name: GetKeyFromSpki - * - * Description: - * This function parses the KMF_X509_SPKI into its - * key and parameter components based on the key generation algorithm. - * NOTE: Currently, it only checks for the RSA and DSA algorithms. - * The RSA algorithm is equivalent to the default behavior. - * All other algorithms will default to the parameters = NULL and the - * key data equal to whatever is in the CSSM_KEY structure for the key - * - * Parameters: - * AlgId (input) : Algorithm identifier - * SpkiPtr (input): SPKI structure that contains the key - * key_ptr(output): The output key - * - */ -KMF_RETURN -GetKeyFromSpki(KMF_ALGORITHM_INDEX AlgId, - KMF_X509_SPKI *SpkiPtr, - KMF_DATA **key_ptr) -{ - KMF_RETURN ret = KMF_OK; - BerElement *asn1; - BerValue *encodedkey = NULL; - - if (!key_ptr || !SpkiPtr) { - return (KMF_ERR_BAD_PARAMETER); - } - *key_ptr = NULL; - - switch (AlgId) { - case KMF_ALGID_DSA: - asn1 = kmfder_alloc(); - if (asn1 == NULL) { - return (KMF_ERR_MEMORY); - } - - if ((ret = encode_spki(asn1, SpkiPtr)) != KMF_OK) { - ret = KMF_ERR_MEMORY; - goto cleanup; - } - - if (kmfber_flatten(asn1, &encodedkey) == -1) { - ret = KMF_ERR_MEMORY; - goto cleanup; - } - - *key_ptr = malloc(sizeof (KMF_DATA)); - - if (!*key_ptr) { - ret = KMF_ERR_MEMORY; - goto cleanup; - } - - (*key_ptr)->Length = encodedkey->bv_len; - (*key_ptr)->Data = (uchar_t *)encodedkey->bv_val; -cleanup: - kmfber_free(asn1, 1); - if (encodedkey) - free(encodedkey); - break; - default: /* RSA */ - *key_ptr = malloc(sizeof (KMF_DATA)); - - if (!*key_ptr) { - return (KMF_ERR_MEMORY); - } - (*key_ptr)->Length = SpkiPtr->subjectPublicKey.Length; - (*key_ptr)->Data = malloc((*key_ptr)->Length); - - if (!(*key_ptr)->Data) { - free(*key_ptr); - *key_ptr = NULL; - return (KMF_ERR_MEMORY); - } - (void) memcpy((*key_ptr)->Data, - SpkiPtr->subjectPublicKey.Data, - (*key_ptr)->Length); - return (ret); - } - return (ret); -} - static KMF_RETURN decode_csr_extensions(BerElement *asn1, KMF_X509_EXTENSIONS *extns) { @@ -2133,7 +2214,6 @@ encode_tbs_csr(BerElement *asn1, KMF_TBS_CSR *tbscsr) if ((ret = encode_spki(asn1, &tbscsr->subjectPublicKeyInfo)) != KMF_OK) goto cleanup; - if ((ret = encode_csr_extensions(asn1, tbscsr)) != KMF_OK) goto cleanup; @@ -2216,6 +2296,56 @@ cleanup: return (rv); } +KMF_RETURN +DerEncodeECPrivateKey(KMF_DATA *encodedkey, KMF_RAW_EC_KEY *eckey) +{ + KMF_RETURN rv = KMF_OK; + BerElement *asn1 = NULL; + uchar_t ver = 1; + BerValue *data = NULL; + + asn1 = kmfder_alloc(); + if (asn1 == NULL) + return (KMF_ERR_MEMORY); + + if (kmfber_printf(asn1, "{io", + ver, eckey->value.val, eckey->value.len) == -1) { + rv = KMF_ERR_ENCODING; + goto cleanup; + } + /* + * Indicate that we are using the named curve option + * for the parameters. + */ + if (kmfber_printf(asn1, "T", 0xA0) == -1) { + rv = KMF_ERR_ENCODING; + goto cleanup; + } + if (kmfber_printf(asn1, "l", eckey->params.Length) == -1) { + rv = KMF_ERR_ENCODING; + goto cleanup; + } + if (kmfber_write(asn1, (char *)eckey->params.Data, + eckey->params.Length, 0) == -1) { + rv = KMF_ERR_ENCODING; + goto cleanup; + } + if (kmfber_printf(asn1, "}") == -1) { + rv = KMF_ERR_ENCODING; + goto cleanup; + } + if (kmfber_flatten(asn1, &data) == -1) { + rv = KMF_ERR_MEMORY; + goto cleanup; + } + encodedkey->Data = (uchar_t *)data->bv_val; + encodedkey->Length = data->bv_len; + +cleanup: + kmfber_free(asn1, 1); + return (rv); +} + KMF_RETURN DerEncodeTbsCsr(KMF_TBS_CSR *tbs_csr_ptr, @@ -2288,7 +2418,7 @@ DerEncodeSignedCsr(KMF_CSR_DATA *signed_csr_ptr, /* Add the Algorithm & Signature Sequence */ if ((ret = encode_algoid(asn1, - &signature->algorithmIdentifier)) != KMF_OK) + &signature->algorithmIdentifier, FALSE)) != KMF_OK) goto cleanup; if (signature->encrypted.Length > 0) { @@ -2325,6 +2455,24 @@ cleanup: return (ret); } +static KMF_RETURN +ber_copy_data(KMF_DATA *dst, KMF_DATA *src) +{ + KMF_RETURN ret = KMF_OK; + + if (dst == NULL || src == NULL) + return (KMF_ERR_BAD_PARAMETER); + + dst->Data = malloc(src->Length); + if (dst->Data == NULL) + return (KMF_ERR_MEMORY); + + dst->Length = src->Length; + (void) memcpy(dst->Data, src->Data, src->Length); + + return (ret); +} + KMF_RETURN ExtractSPKIData( const KMF_X509_SPKI *pKey, @@ -2388,6 +2536,16 @@ ExtractSPKIData( *uNumKeyParts = KMF_NUMBER_DSA_PUBLIC_KEY_PARTS; break; + case KMF_ALGID_SHA1WithECDSA: + case KMF_ALGID_ECDSA: + (void) ber_copy_data(&pKeyParts[KMF_ECDSA_PARAMS], + (KMF_DATA *)&pKey->algorithm.parameters); + + (void) ber_copy_data(&pKeyParts[KMF_ECDSA_POINT], + (KMF_DATA *)&pKey->subjectPublicKey); + + *uNumKeyParts = 2; + break; case KMF_ALGID_RSA: case KMF_ALGID_MD2WithRSA: diff --git a/usr/src/lib/libkmf/ber_der/common/decode.c b/usr/src/lib/libkmf/ber_der/common/decode.c index 459c49fdbe..cdae8d84a9 100644 --- a/usr/src/lib/libkmf/ber_der/common/decode.c +++ b/usr/src/lib/libkmf/ber_der/common/decode.c @@ -1,5 +1,5 @@ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* @@ -345,10 +345,10 @@ ber_get_bigint(BerElement *ber, struct berval **bv) (*bv)->bv_len = len; - /* If DER encoding, strip leading 0's */ + /* If DER encoding, strip leading 0's if high-order bit is set */ if (ber->ber_options & KMFBER_OPT_USE_DER) { char *p = (*bv)->bv_val; - while ((*p == 0x00) && ((*bv)->bv_len > 0)) { + while ((*p == 0x00) && ((*bv)->bv_len > 0) && (p[1] & 0x80)) { p++; (*bv)->bv_len--; } diff --git a/usr/src/lib/libkmf/ber_der/common/mapfile-vers b/usr/src/lib/libkmf/ber_der/common/mapfile-vers index 0a97cd2eab..cda7690c8d 100644 --- a/usr/src/lib/libkmf/ber_der/common/mapfile-vers +++ b/usr/src/lib/libkmf/ber_der/common/mapfile-vers @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -43,6 +43,7 @@ SUNWprivate_1.1 { CopyRDN; CopySPKI; DerDecodeDSASignature; + DerDecodeECDSASignature; DerDecodeExtension; DerDecodeName; DerDecodeSPKI; @@ -52,6 +53,8 @@ SUNWprivate_1.1 { DerDecodeTbsCsr; DerEncodeDSAPrivateKey; DerEncodeDSASignature; + DerEncodeECDSASignature; + DerEncodeECPrivateKey; DerEncodeName; DerEncodeRSAPrivateKey; DerEncodeSPKI; @@ -61,7 +64,6 @@ SUNWprivate_1.1 { DerEncodeTbsCsr; ExtractSPKIData; ExtractX509CertParts; - GetKeyFromSpki; kmfber_alloc; kmfber_bvfree; kmfber_first_element; diff --git a/usr/src/lib/libkmf/ber_der/inc/ber_der.h b/usr/src/lib/libkmf/ber_der/inc/ber_der.h index abf112351d..4c2da6c91a 100644 --- a/usr/src/lib/libkmf/ber_der/inc/ber_der.h +++ b/usr/src/lib/libkmf/ber_der/inc/ber_der.h @@ -1,11 +1,9 @@ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* - * Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 - * * The contents of this file are subject to the Netscape Public License * Version 1.0(the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at @@ -143,8 +141,6 @@ extern KMF_RETURN DerDecodeTbsCsr(const KMF_DATA *, KMF_TBS_CSR **); extern KMF_RETURN DerEncodeTbsCsr(KMF_TBS_CSR *, KMF_DATA *); KMF_RETURN ExtractX509CertParts(KMF_DATA *, KMF_DATA *, KMF_DATA *); -KMF_RETURN GetKeyFromSpki(KMF_ALGORITHM_INDEX, KMF_X509_SPKI *, - KMF_DATA **); extern KMF_RETURN DerEncodeName(KMF_X509_NAME *, KMF_DATA *); KMF_RETURN DerDecodeName(KMF_DATA *, KMF_X509_NAME *); KMF_RETURN DerDecodeExtension(KMF_DATA *, KMF_X509_EXTENSION **); @@ -154,6 +150,8 @@ KMF_RETURN CopySPKI(KMF_X509_SPKI *, extern KMF_RETURN DerDecodeSPKI(KMF_DATA *, KMF_X509_SPKI *); extern KMF_RETURN DerDecodeDSASignature(KMF_DATA *, KMF_DATA *); extern KMF_RETURN DerEncodeDSASignature(KMF_DATA *, KMF_DATA *); +extern KMF_RETURN DerEncodeECDSASignature(KMF_DATA *, KMF_DATA *); +extern KMF_RETURN DerDecodeECDSASignature(KMF_DATA *, KMF_DATA *); KMF_RETURN DerEncodeAlgoid(KMF_DATA *, KMF_DATA *); KMF_RETURN DerDecodeSPKI(KMF_DATA *, KMF_X509_SPKI *); KMF_RETURN DerEncodeSPKI(KMF_X509_SPKI *, KMF_DATA *); @@ -162,5 +160,6 @@ extern KMF_RETURN ExtractSPKIData(const KMF_X509_SPKI *, extern KMF_RETURN AddRDN(KMF_X509_NAME *, KMF_X509_RDN *); KMF_RETURN DerEncodeRSAPrivateKey(KMF_DATA *, KMF_RAW_RSA_KEY *); KMF_RETURN DerEncodeDSAPrivateKey(KMF_DATA *, KMF_RAW_DSA_KEY *); +KMF_RETURN DerEncodeECPrivateKey(KMF_DATA *, KMF_RAW_EC_KEY *); #endif /* BER_DER_H */ diff --git a/usr/src/lib/libkmf/include/algorithm.h b/usr/src/lib/libkmf/include/algorithm.h deleted file mode 100644 index 00e2eabddf..0000000000 --- a/usr/src/lib/libkmf/include/algorithm.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ -/* - * Copyright (c) 1995-2000 Intel Corporation. All rights reserved. - */ - -#ifndef _ALGORITHM_H -#define _ALGORITHM_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <kmftypes.h> -#include <security/cryptoki.h> - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct pkcs_algorithm_map -{ - CK_MECHANISM_TYPE pkcs_mechanism; - uint32_t algorithm; - uint32_t context_type; - uint32_t enc_mode; - CK_BBOOL bMultiPart; - CK_BBOOL fix_keylength; - uint32_t keylength; - CK_BBOOL fix_blocksize; - uint32_t block_size; - CK_BBOOL requires_iv; - uint32_t iv_length; - CK_FLAGS required_flags; - CK_KEY_TYPE key_type; - char *szDescription; -} PKCS_ALGORITHM_MAP; - -extern KMF_SIGNATURE_MODE PKCS_GetDefaultSignatureMode(KMF_ALGORITHM_INDEX); -extern PKCS_ALGORITHM_MAP* pkcs_get_alg_map(KMF_ALGCLASS, uint32_t, - uint32_t); - -#ifdef __cplusplus -} -#endif - -#endif /* _ALGORITHM_H */ diff --git a/usr/src/lib/libkmf/include/kmfapiP.h b/usr/src/lib/libkmf/include/kmfapiP.h index 1e0d108f92..27deeb460c 100644 --- a/usr/src/lib/libkmf/include/kmfapiP.h +++ b/usr/src/lib/libkmf/include/kmfapiP.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _KMFAPIP_H @@ -143,13 +143,6 @@ typedef struct { KMF_HANDLE_T, int, KMF_ATTRIBUTE *); - KMF_RETURN (*VerifyDataWithCert) ( - KMF_HANDLE_T, - KMF_ALGORITHM_INDEX, - KMF_DATA *, - KMF_DATA *, - KMF_DATA *); - KMF_RETURN (*StoreKey) ( KMF_HANDLE_T, int, @@ -224,6 +217,10 @@ VerifyDataWithKey(KMF_HANDLE_T, KMF_DATA *, KMF_ALGORITHM_INDEX, extern KMF_BOOL pkcs_algid_to_keytype( KMF_ALGORITHM_INDEX, CK_KEY_TYPE *); +extern KMF_RETURN PKCS_DigestData(KMF_HANDLE_T, + CK_SESSION_HANDLE, CK_MECHANISM_TYPE, + KMF_DATA *, KMF_DATA *, boolean_t); + extern KMF_RETURN PKCS_VerifyData( KMF_HANDLE *, KMF_ALGORITHM_INDEX, @@ -247,10 +244,6 @@ extern KMF_RETURN copy_algoid(KMF_X509_ALGORITHM_IDENTIFIER *destid, extern KMF_OID *x509_algid_to_algoid(KMF_ALGORITHM_INDEX); extern KMF_ALGORITHM_INDEX x509_algoid_to_algid(KMF_OID *); -extern KMF_RETURN PKCS_AcquirePublicKeyHandle(CK_SESSION_HANDLE ckSession, - const KMF_X509_SPKI *, CK_KEY_TYPE, CK_OBJECT_HANDLE *, - KMF_BOOL *); - extern KMF_RETURN GetIDFromSPKI(KMF_X509_SPKI *, KMF_DATA *); extern KMF_RETURN kmf_select_token(KMF_HANDLE_T, char *, int); extern KMF_RETURN kmf_set_altname(KMF_X509_EXTENSIONS *, @@ -295,6 +288,9 @@ extern KMF_RETURN test_attributes(int, KMF_ATTRIBUTE_TESTER *, #define KMF_DSA_BASE (2) #define KMF_DSA_PUBLIC_VALUE (3) +#define KMF_ECDSA_PARAMS (0) +#define KMF_ECDSA_POINT (1) + #ifndef max #define max(a, b) ((a) < (b) ? (b) : (a)) #endif @@ -341,7 +337,10 @@ typedef struct conf_entrylist { struct conf_entrylist *next; } conf_entrylist_t; - +extern KMF_RETURN get_pk11_data(KMF_ALGORITHM_INDEX, + CK_KEY_TYPE *, CK_MECHANISM_TYPE *, CK_MECHANISM_TYPE *, boolean_t); +extern KMF_RETURN kmf_create_pk11_session(CK_SESSION_HANDLE *, + CK_MECHANISM_TYPE, CK_FLAGS); extern KMF_RETURN get_entrylist(conf_entrylist_t **); extern void free_entrylist(conf_entrylist_t *); extern void free_entry(conf_entry_t *); diff --git a/usr/src/lib/libkmf/include/kmftypes.h b/usr/src/lib/libkmf/include/kmftypes.h index dbbf680537..01e38862dc 100644 --- a/usr/src/lib/libkmf/include/kmftypes.h +++ b/usr/src/lib/libkmf/include/kmftypes.h @@ -115,6 +115,9 @@ typedef enum { * Algorithms * This type defines a set of constants used to identify cryptographic * algorithms. + * + * When adding new ALGID, be careful not to rearrange existing + * values, doing so can cause problem in the STC test suite. */ typedef enum { KMF_ALGID_NONE = 0, @@ -125,7 +128,20 @@ typedef enum { KMF_ALGID_MD5WithRSA, KMF_ALGID_MD2WithRSA, KMF_ALGID_SHA1WithRSA, - KMF_ALGID_SHA1WithDSA + KMF_ALGID_SHA1WithDSA, + + KMF_ALGID_ECDSA, + + KMF_ALGID_SHA256WithRSA, + KMF_ALGID_SHA384WithRSA, + KMF_ALGID_SHA512WithRSA, + + KMF_ALGID_SHA256WithDSA, + + KMF_ALGID_SHA1WithECDSA, + KMF_ALGID_SHA256WithECDSA, + KMF_ALGID_SHA384WithECDSA, + KMF_ALGID_SHA512WithECDSA } KMF_ALGORITHM_INDEX; /* @@ -146,7 +162,8 @@ typedef enum { KMF_RC4 = 4, KMF_DES = 5, KMF_DES3 = 6, - KMF_GENERIC_SECRET = 7 + KMF_GENERIC_SECRET = 7, + KMF_ECDSA = 8 }KMF_KEY_ALG; typedef enum { @@ -156,7 +173,6 @@ typedef enum { KMF_SYMMETRIC = 3 /* symmetric key */ }KMF_KEY_CLASS; - typedef enum { KMF_CERT = 0, KMF_CSR = 1, @@ -187,6 +203,11 @@ typedef struct { } KMF_RAW_SYM_KEY; typedef struct { + KMF_BIGINT value; + KMF_OID params; +} KMF_RAW_EC_KEY; + +typedef struct { KMF_KEY_ALG keytype; boolean_t sensitive; boolean_t not_extractable; @@ -194,6 +215,7 @@ typedef struct { KMF_RAW_RSA_KEY rsa; KMF_RAW_DSA_KEY dsa; KMF_RAW_SYM_KEY sym; + KMF_RAW_EC_KEY ec; }rawdata; char *label; KMF_DATA id; @@ -355,20 +377,6 @@ typedef enum { } KMF_OCSP_REVOKED_STATUS; typedef enum { - KMF_ALGCLASS_NONE = 0, - KMF_ALGCLASS_CUSTOM, - KMF_ALGCLASS_SIGNATURE, - KMF_ALGCLASS_SYMMETRIC, - KMF_ALGCLASS_DIGEST, - KMF_ALGCLASS_RANDOMGEN, - KMF_ALGCLASS_UNIQUEGEN, - KMF_ALGCLASS_MAC, - KMF_ALGCLASS_ASYMMETRIC, - KMF_ALGCLASS_KEYGEN, - KMF_ALGCLASS_DERIVEKEY -} KMF_ALGCLASS; - -typedef enum { KMF_CERT_ISSUER = 1, KMF_CERT_SUBJECT, KMF_CERT_VERSION, @@ -786,7 +794,8 @@ typedef enum { KMF_CIPHERTEXT_DATA_ATTR, KMF_VALIDATE_RESULT_ATTR, KMF_KEY_DATA_ATTR, - KMF_PK11_USER_TYPE_ATTR + KMF_PK11_USER_TYPE_ATTR, + KMF_ECC_CURVE_OID_ATTR } KMF_ATTR_TYPE; typedef struct { @@ -1155,11 +1164,14 @@ KMFOID_PKIX_KP_OCSPSigning, KMFOID_SHA1, KMFOID_RSA, KMFOID_DSA, +KMFOID_MD5, KMFOID_MD5WithRSA, KMFOID_MD2WithRSA, KMFOID_SHA1WithRSA, +KMFOID_SHA256WithRSA, +KMFOID_SHA384WithRSA, +KMFOID_SHA512WithRSA, KMFOID_SHA1WithDSA, -KMFOID_OIW_DSAWithSHA1, KMFOID_X9CM_DSA, KMFOID_X9CM_DSAWithSHA1; @@ -1171,6 +1183,79 @@ KMFOID_PKINIT_Kdc, KMFOID_MS_KP_SCLogon, KMFOID_MS_KP_SCLogon_UPN; +/* For ECC support */ +extern const KMF_OID +KMFOID_EC_PUBLIC_KEY, +KMFOID_SHA1WithECDSA, +KMFOID_SHA224WithECDSA, +KMFOID_SHA256WithECDSA, +KMFOID_SHA384WithECDSA, +KMFOID_SHA512WithECDSA, +KMFOID_SHA224WithDSA, +KMFOID_SHA256WithDSA, +KMFOID_SHA224, +KMFOID_SHA256, +KMFOID_SHA384, +KMFOID_SHA512, +KMFOID_ECC_secp112r1, +KMFOID_ECC_secp112r2, +KMFOID_ECC_secp128r1, +KMFOID_ECC_secp128r2, +KMFOID_ECC_secp160k1, +KMFOID_ECC_secp160r1, +KMFOID_ECC_secp160r2, +KMFOID_ECC_secp192k1, +KMFOID_ECC_secp224k1, +KMFOID_ECC_secp224r1, +KMFOID_ECC_secp256k1, +KMFOID_ECC_secp384r1, +KMFOID_ECC_secp521r1, +KMFOID_ECC_sect113r1, +KMFOID_ECC_sect113r2, +KMFOID_ECC_sect131r1, +KMFOID_ECC_sect131r2, +KMFOID_ECC_sect163k1, +KMFOID_ECC_sect163r1, +KMFOID_ECC_sect163r2, +KMFOID_ECC_sect193r1, +KMFOID_ECC_sect193r2, +KMFOID_ECC_sect233k1, +KMFOID_ECC_sect233r1, +KMFOID_ECC_sect239k1, +KMFOID_ECC_sect283k1, +KMFOID_ECC_sect283r1, +KMFOID_ECC_sect409k1, +KMFOID_ECC_sect409r1, +KMFOID_ECC_sect571k1, +KMFOID_ECC_sect571r1, +KMFOID_ECC_c2pnb163v1, +KMFOID_ECC_c2pnb163v2, +KMFOID_ECC_c2pnb163v3, +KMFOID_ECC_c2pnb176v1, +KMFOID_ECC_c2tnb191v1, +KMFOID_ECC_c2tnb191v2, +KMFOID_ECC_c2tnb191v3, +KMFOID_ECC_c2pnb208w1, +KMFOID_ECC_c2tnb239v1, +KMFOID_ECC_c2tnb239v2, +KMFOID_ECC_c2tnb239v3, +KMFOID_ECC_c2pnb272w1, +KMFOID_ECC_c2pnb304w1, +KMFOID_ECC_c2tnb359v1, +KMFOID_ECC_c2pnb368w1, +KMFOID_ECC_c2tnb431r1, +KMFOID_ECC_prime192v2, +KMFOID_ECC_prime192v3, +KMFOID_ECC_secp192r1, +KMFOID_ECC_secp256r1; + +/* + * ANSI X9-62 prime192v1 is same as secp192r1 and + * ANSI X9-62 prime256v1 is same as secp256r1 + */ +#define KMFOID_ANSIX962_prime192v1 KMFOID_ECC_secp192r1 +#define KMFOID_ANSIX962_prime256v1 KMFOID_ECC_secp256r1 + /* * KMF Certificate validation codes. These may be masked together. */ diff --git a/usr/src/lib/libkmf/libkmf/Makefile.com b/usr/src/lib/libkmf/libkmf/Makefile.com index af34cf87a3..b11f172a71 100644 --- a/usr/src/lib/libkmf/libkmf/Makefile.com +++ b/usr/src/lib/libkmf/libkmf/Makefile.com @@ -18,7 +18,7 @@ # # CDDL HEADER END # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -27,7 +27,6 @@ VERS= .1 OBJECTS= \ algoid.o \ - algorithm.o \ certgetsetop.o \ certop.o \ client.o \ diff --git a/usr/src/lib/libkmf/libkmf/common/algoid.c b/usr/src/lib/libkmf/libkmf/common/algoid.c index f33634f007..51804af492 100644 --- a/usr/src/lib/libkmf/libkmf/common/algoid.c +++ b/usr/src/lib/libkmf/libkmf/common/algoid.c @@ -2,12 +2,10 @@ * Copyright (c) 1995-2000 Intel Corporation. All rights reserved. */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <stdlib.h> #include <string.h> @@ -28,9 +26,17 @@ static KMF_OID_ID ALGOID_ID_Table[] = { {(KMF_OID *)&KMFOID_RSA, KMF_ALGID_RSA}, {(KMF_OID *)&KMFOID_DSA, KMF_ALGID_DSA}, {(KMF_OID *)&KMFOID_MD5WithRSA, KMF_ALGID_MD5WithRSA}, - {(KMF_OID *)&KMFOID_MD2WithRSA, KMF_ALGID_MD2WithRSA}, {(KMF_OID *)&KMFOID_SHA1WithRSA, KMF_ALGID_SHA1WithRSA}, - {(KMF_OID *)&KMFOID_SHA1WithDSA, KMF_ALGID_SHA1WithDSA} + {(KMF_OID *)&KMFOID_SHA1WithDSA, KMF_ALGID_SHA1WithDSA}, + {(KMF_OID *)&KMFOID_SHA256WithDSA, KMF_ALGID_SHA256WithDSA}, + {(KMF_OID *)&KMFOID_SHA1WithECDSA, KMF_ALGID_SHA1WithECDSA}, + {(KMF_OID *)&KMFOID_SHA256WithECDSA, KMF_ALGID_SHA256WithECDSA}, + {(KMF_OID *)&KMFOID_SHA256WithRSA, KMF_ALGID_SHA256WithRSA}, + {(KMF_OID *)&KMFOID_SHA384WithECDSA, KMF_ALGID_SHA384WithECDSA}, + {(KMF_OID *)&KMFOID_SHA384WithRSA, KMF_ALGID_SHA384WithRSA}, + {(KMF_OID *)&KMFOID_SHA512WithECDSA, KMF_ALGID_SHA512WithECDSA}, + {(KMF_OID *)&KMFOID_SHA512WithRSA, KMF_ALGID_SHA512WithRSA}, + {(KMF_OID *)&KMFOID_EC_PUBLIC_KEY, KMF_ALGID_ECDSA} }; #define NUM_ALGOIDS ((sizeof (ALGOID_ID_Table))/(sizeof (ALGOID_ID_Table[0]))) diff --git a/usr/src/lib/libkmf/libkmf/common/algorithm.c b/usr/src/lib/libkmf/libkmf/common/algorithm.c deleted file mode 100644 index d0ed3912a3..0000000000 --- a/usr/src/lib/libkmf/libkmf/common/algorithm.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) 1995-2000 Intel Corporation. All rights reserved. - */ -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <kmfapiP.h> -#include <algorithm.h> -#include <security/cryptoki.h> - -typedef struct _pkcs_key_type_map -{ - KMF_ALGORITHM_INDEX kmfAlgorithmId; - CK_KEY_TYPE ckKeyType; -} -PKCS_KEY_TYPE_MAP; - -static const PKCS_KEY_TYPE_MAP _PKCS2KMFKeyTypeMap[] = { - { KMF_ALGID_RSA, CKK_RSA }, - { KMF_ALGID_DSA, CKK_DSA } -}; - -#define SUP(_ckmech_, _kmfalg_, _kmfcls_, _kmfmode_, _multi_, \ - _fixkelen_, _keylen_, _fixblksz_, _blksz_, _reqiv_, _ivlen_,\ - _regalgflg_, _keytype_, _desc_) \ - { _ckmech_, _kmfalg_, _kmfcls_, _kmfmode_, _multi_, _fixkelen_,\ - _keylen_, _fixblksz_, _blksz_, _reqiv_, _ivlen_, _regalgflg_,\ - _keytype_, _desc_ }, - -static const PKCS_ALGORITHM_MAP _PKCS2KMFMap[] = { -/* - * PKCS #11 Mechanism, - * Alg. ID - * Alg. Class - * Alg. Mode - * Milti-Part - * Fix Key Length - * Key Length - * Fix Block Size - * Block Size - * Needs IV - * IV Length - * Alg. Flags - * Type - * Description - */ -SUP(CKM_RSA_PKCS_KEY_PAIR_GEN, KMF_ALGID_RSA, KMF_ALGCLASS_KEYGEN,\ - KMF_ALGMODE_NONE, 0, 0, 0,\ - 0, 0, 0, 0, CKF_GENERATE_KEY_PAIR,\ - CKK_RSA, "RSA PKCS #1 Key Pair Generation") -SUP(CKM_RSA_X_509, KMF_ALGID_RSA, KMF_ALGCLASS_ASYMMETRIC, KMF_ALGMODE_NONE, - 0, 0, 0, 0, 0, 0, 0, CKF_ENCRYPT, - CKK_RSA, "RSA RAW Encryption") -SUP(CKM_RSA_X_509, KMF_ALGID_RSA, KMF_ALGCLASS_ASYMMETRIC, KMF_ALGMODE_NONE, - 0, 0, 0, 0, 0, 0, 0, CKF_SIGN_RECOVER, - CKK_RSA, "RSA RAW Private Key Encryption") -SUP(CKM_RSA_X_509, KMF_ALGID_RSA, KMF_ALGCLASS_SIGNATURE, KMF_ALGMODE_NONE, - 0, 0, 0, 0, 0, 0, 0, CKF_SIGN, - CKK_RSA, "RSA RAW Signature") -SUP(CKM_RSA_PKCS, KMF_ALGID_RSA, KMF_ALGCLASS_SIGNATURE, - KMF_ALGMODE_PKCS1_EMSA_V15, - 0, 0, 0, 0, 0, 0, 0, CKF_SIGN, CKK_RSA, - "RSA PKCS #1 Signature") -SUP(CKM_MD2_RSA_PKCS, KMF_ALGID_MD2WithRSA, KMF_ALGCLASS_SIGNATURE, - KMF_ALGMODE_PKCS1_EMSA_V15, 1, 0, 0, 0, 0, - 0, 0, CKF_SIGN, CKK_RSA, "MD2 w/RSA Signature") -SUP(CKM_MD5_RSA_PKCS, KMF_ALGID_MD5WithRSA, KMF_ALGCLASS_SIGNATURE, - KMF_ALGMODE_PKCS1_EMSA_V15, 1, 0, 0, 0, 0, - 0, 0, CKF_SIGN, CKK_RSA, "MD5 w/RSA Signature") -SUP(CKM_SHA1_RSA_PKCS, KMF_ALGID_SHA1WithRSA, KMF_ALGCLASS_SIGNATURE, - KMF_ALGMODE_PKCS1_EMSA_V15, 1, 0, 0, 0, 0, - 0, 0, CKF_SIGN, CKK_RSA, "SHA-1 w/RSA Signature") - -SUP(CKM_DSA_KEY_PAIR_GEN, KMF_ALGID_DSA, KMF_ALGCLASS_KEYGEN, KMF_ALGMODE_NONE, - 0, 0, 0, 0, 0, 0, 0, - CKF_GENERATE_KEY_PAIR, CKK_DSA, "DSA Key Pair Generation") - -SUP(CKM_DSA, KMF_ALGID_DSA, KMF_ALGCLASS_SIGNATURE, KMF_ALGMODE_NONE, - 0, 0, 0, 0, 0, 0, 0, CKF_SIGN, - CKK_DSA, "DSA Signature") - -SUP(CKM_DSA_SHA1, KMF_ALGID_SHA1WithDSA, KMF_ALGCLASS_SIGNATURE, - KMF_ALGMODE_NONE, 1, 0, 0, 0, 0, 0, - 0, CKF_SIGN, CKK_DSA, "SHA-1 w/DSA Signature") - -SUP(CKM_SHA_1, KMF_ALGID_SHA1, KMF_ALGCLASS_DIGEST, KMF_ALGMODE_NONE, - 1, 1, 20, 0, 0, 0, 0, CKF_DIGEST, (CK_KEY_TYPE)-1, "SHA-1") -}; - -/* Undefine the macro definitions */ -#undef SUP - -/* Number of items in the algorithm map table */ -#define _PKCS2KMFMapCount (\ - sizeof (_PKCS2KMFMap) / sizeof (_PKCS2KMFMap[0])) - -/* Indicator that the algorithm was not found */ -#define PKCS_ALGORITHM_NOT_FOUND ((uint32_t)(~0)) - -/* - * Name: pkcs_get_alg_map - * - * Description: - * Searches the _PKCS2KMFMap table for a matching set of alg. - * description parameters. - * - * Parameters: - * algType (input) - KMF_ALGCLASS_* identifier to match. - * algID (input) - KMF_ALGID_* identifier to match. - * mode (input) - KMF_ALGMODE_* identifier to match. Use - * KMF_ALGMODE_NONE if a mode does not apply. - * - * Returns: - * Pointer to the lookup table entry that matches requested parameters. - * Ptr->keylength will equal PKCS11CONVERT_NOT_FOUND if no match is found. - */ -PKCS_ALGORITHM_MAP * -pkcs_get_alg_map(KMF_ALGCLASS algType, uint32_t algID, uint32_t mode) -{ - uint32_t i = 0; - - for (i = 0; i < _PKCS2KMFMapCount; i++) { - if ((_PKCS2KMFMap[i].context_type == algType) && - (_PKCS2KMFMap[i].algorithm == algID) && - (_PKCS2KMFMap[i].enc_mode == mode)) { - return ((PKCS_ALGORITHM_MAP *)&(_PKCS2KMFMap[i])); - } - } - - return (NULL); -} - -KMF_BOOL -pkcs_algid_to_keytype(KMF_ALGORITHM_INDEX AlgId, - CK_KEY_TYPE *pckKeyType) -{ - uint32_t uIndex; - uint32_t uMapSize = - sizeof (_PKCS2KMFKeyTypeMap) / sizeof (PKCS_KEY_TYPE_MAP); - - for (uIndex = 0; uIndex < uMapSize; uIndex++) { - if (_PKCS2KMFKeyTypeMap[uIndex].kmfAlgorithmId == AlgId) { - *pckKeyType = _PKCS2KMFKeyTypeMap[uIndex].ckKeyType; - return (1); - } - } - - return (0); -} diff --git a/usr/src/lib/libkmf/libkmf/common/certop.c b/usr/src/lib/libkmf/libkmf/common/certop.c index da56202051..3302fa8de5 100644 --- a/usr/src/lib/libkmf/libkmf/common/certop.c +++ b/usr/src/lib/libkmf/libkmf/common/certop.c @@ -71,13 +71,23 @@ get_keyalg_from_cert(KMF_DATA *cert, KMF_KEY_ALG *keyalg) switch (AlgorithmId) { case KMF_ALGID_MD5WithRSA: - case KMF_ALGID_MD2WithRSA: case KMF_ALGID_SHA1WithRSA: + case KMF_ALGID_SHA256WithRSA: + case KMF_ALGID_SHA384WithRSA: + case KMF_ALGID_SHA512WithRSA: *keyalg = KMF_RSA; break; case KMF_ALGID_SHA1WithDSA: + case KMF_ALGID_SHA256WithDSA: *keyalg = KMF_DSA; break; + case KMF_ALGID_SHA1WithECDSA: + case KMF_ALGID_SHA256WithECDSA: + case KMF_ALGID_SHA384WithECDSA: + case KMF_ALGID_SHA512WithECDSA: + case KMF_ALGID_ECDSA: + *keyalg = KMF_ECDSA; + break; default: rv = KMF_ERR_BAD_ALGORITHM; } @@ -410,8 +420,8 @@ kmf_sign_cert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) int freethekey = 0; KMF_POLICY_RECORD *policy; KMF_OID *oid = NULL; - KMF_ALGORITHM_INDEX AlgId; KMF_X509_CERTIFICATE *x509cert; + KMF_X509_TBS_CERT *decodedTbsCert = NULL; KMF_ATTRIBUTE_TESTER required_attrs[] = { {KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)}, {KMF_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA), sizeof (KMF_DATA)} @@ -466,18 +476,6 @@ kmf_sign_cert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) } sign_key_ptr = &sign_key; freethekey = 1; - - ret = get_sigalg_from_cert(signer_cert, &AlgId); - if (ret != KMF_OK) - goto out; - else - oid = x509_algid_to_algoid(AlgId); - } else if (sign_key_ptr != NULL) { - if (sign_key_ptr->keyalg == KMF_RSA) { - oid = (KMF_OID *)&KMFOID_SHA1WithRSA; - } else if (sign_key_ptr->keyalg == KMF_DSA) { - oid = (KMF_OID *)&KMFOID_SHA1WithDSA; - } } /* Now we are ready to sign */ @@ -490,11 +488,22 @@ kmf_sign_cert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) ret = KMF_ERR_BAD_PARAMETER; goto out; } + + /* determine signature OID from cert request */ + oid = CERT_ALG_OID(x509cert); + ret = kmf_encode_cert_record(x509cert, &unsignedCert); - if (ret == KMF_OK) - tbs_cert = &unsignedCert; - else + if (ret != KMF_OK) goto out; + + tbs_cert = &unsignedCert; + } + /* If OID still not found, decode the TBS Cert and pull it out */ + if (oid == NULL) { + ret = DerDecodeTbsCertificate(tbs_cert, &decodedTbsCert); + if (ret != KMF_OK) + goto out; + oid = &decodedTbsCert->signature.algorithm; } signed_cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, @@ -515,6 +524,10 @@ out: kmf_free_kmf_key(handle, &sign_key); kmf_free_data(&unsignedCert); + if (decodedTbsCert != NULL) { + kmf_free_tbs_cert(decodedTbsCert); + free(decodedTbsCert); + } return (ret); } @@ -564,7 +577,7 @@ kmf_sign_data(KMF_HANDLE_T handle, int numattr, KMF_DATA *tbs_data = NULL; /* to be signed data */ KMF_DATA *output = NULL; KMF_KEY_HANDLE sign_key, *sign_key_ptr; - KMF_ALGORITHM_INDEX AlgId; + KMF_ALGORITHM_INDEX AlgId = KMF_ALGID_NONE; KMF_DATA signature = {0, NULL}; KMF_OID *oid; KMF_POLICY_RECORD *policy; @@ -665,9 +678,7 @@ kmf_sign_data(KMF_HANDLE_T handle, int numattr, ret = get_sigalg_from_cert(signer_cert, &AlgId); if (ret != KMF_OK) goto cleanup; - else - oid = x509_algid_to_algoid(AlgId); - + oid = x509_algid_to_algoid(AlgId); } else if (oid == NULL && ret == KMF_OK) { /* AlgID was given by caller, convert it to OID */ oid = x509_algid_to_algoid(AlgId); @@ -691,13 +702,15 @@ kmf_sign_data(KMF_HANDLE_T handle, int numattr, /* * For DSA, NSS returns an encoded signature. Decode the - * signature as DSA signature should be 40-byte long. + * signature and expect a 40-byte DSA signature. */ if (plugin->type == KMF_KEYSTORE_NSS && - AlgId == KMF_ALGID_SHA1WithDSA) { + (AlgId == KMF_ALGID_SHA1WithDSA || + AlgId == KMF_ALGID_SHA256WithDSA)) { ret = DerDecodeDSASignature(output, &signature); if (ret != KMF_OK) goto cleanup; + output->Length = signature.Length; (void) memcpy(output->Data, signature.Data, signature.Length); } @@ -712,7 +725,6 @@ cleanup: if (signer_cert != NULL && sign_key_ptr != NULL) kmf_free_kmf_key(handle, sign_key_ptr); - return (ret); } @@ -806,6 +818,8 @@ kmf_verify_data(KMF_HANDLE_T handle, /* If the caller passed a signer cert instead of a key use it. */ if (signer_cert != NULL) { + KMF_X509_CERTIFICATE *SignerCert = NULL; + policy = handle->policy; ret = check_key_usage(handle, signer_cert, KMF_KU_SIGN_DATA); if (ret == KMF_ERR_EXTENSION_NOT_FOUND && policy->ku_bits == 0) @@ -813,17 +827,35 @@ kmf_verify_data(KMF_HANDLE_T handle, if (ret != KMF_OK) return (ret); - if (kstype == KMF_KEYSTORE_NSS) - kstype = KMF_KEYSTORE_PK11TOKEN; - plugin = FindPlugin(handle, kstype); - if (plugin == NULL) - return (KMF_ERR_PLUGIN_NOTFOUND); - if (plugin->funclist->VerifyDataWithCert == NULL) - return (KMF_ERR_FUNCTION_NOT_FOUND); + /* Decode the signer cert so we can get the SPKI data */ + ret = DerDecodeSignedCertificate(signer_cert, &SignerCert); + if (ret != KMF_OK) + return (ret); - CLEAR_ERROR(handle, ret); - ret = plugin->funclist->VerifyDataWithCert(handle, - sigAlg, indata, insig, signer_cert); + /* If no algorithm specified, use the certs signature alg */ + if (sigAlg == KMF_ALGID_NONE) + sigAlg = x509_algoid_to_algid(CERT_ALG_OID(SignerCert)); + + if (sigAlg == KMF_ALGID_NONE) { + kmf_free_signed_cert(SignerCert); + free(SignerCert); + return (KMF_ERR_BAD_ALGORITHM); + } + + /* + * Verify the data locally (i.e. using PKCS#11). + * The verify operation uses a public key and does not + * require access to a specific keystore. Save time + * (and code) by just using the frameworks implementation + * of the verify operation using crypto framework + * APIs. + */ + ret = PKCS_VerifyData(handle, sigAlg, + &SignerCert->certificate.subjectPublicKeyInfo, + indata, insig); + + kmf_free_signed_cert(SignerCert); + free(SignerCert); } else { /* Retrieve public key data from keystore */ plugin = FindPlugin(handle, kstype); @@ -836,10 +868,9 @@ kmf_verify_data(KMF_HANDLE_T handle, } ret = DerDecodeSPKI(&derkey, &spki); - if (ret == KMF_OK) { + if (ret == KMF_OK) ret = PKCS_VerifyData(handle, sigAlg, &spki, indata, insig); - } if (derkey.Data != NULL) free(derkey.Data); @@ -946,54 +977,6 @@ kmf_verify_cert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) } /* - * Utility routine for verifying generic data using a - * certificate to derive the public key. This is - * done in a specific plugin because there are situations - * where we want to force this operation to happen in - * a specific keystore. - * For example: - * libelfsign.so.1 verifies signatures on crypto libraries. - * We must use pkcs11 functions to verify the pkcs11 - * plugins in order to keep the validation within the - * Cryptographic Framework's FIPS-140 boundary. To avoid - * a circular dependency, pksc11_softtoken.so.1 is - * interposed by libkcfd.so.1 via kcfd, which prevents - * libpkcs11.so.1's interfaces from being used when libkmf.so.1 - * is called from kcfd. - */ -static KMF_RETURN -plugin_verify_data_with_cert(KMF_HANDLE_T handle, - KMF_KEYSTORE_TYPE kstype, - KMF_ALGORITHM_INDEX algid, - KMF_DATA *indata, - KMF_DATA *insig, - const KMF_DATA *SignerCert) -{ - KMF_PLUGIN *plugin; - KMF_RETURN ret = KMF_OK; - - /* - * If NSS, use PKCS#11, we are not accessing the database(s), - * we just prefer the "verify" operation from the crypto framework. - */ - if (kstype == KMF_KEYSTORE_NSS) - kstype = KMF_KEYSTORE_PK11TOKEN; - - plugin = FindPlugin(handle, kstype); - if (plugin == NULL) - return (KMF_ERR_PLUGIN_NOTFOUND); - - if (plugin->funclist->VerifyDataWithCert == NULL) - return (KMF_ERR_FUNCTION_NOT_FOUND); - - CLEAR_ERROR(handle, ret); - ret = (plugin->funclist->VerifyDataWithCert(handle, - algid, indata, insig, (KMF_DATA *)SignerCert)); - - return (ret); -} - -/* * Name: kmf_encrypt * * Description: @@ -1078,8 +1061,15 @@ kmf_encrypt(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) algid = x509_algoid_to_algid(alg); - /* DSA does not support encrypt */ - if (algid == KMF_ALGID_DSA || algid == KMF_ALGID_NONE) { + /* [EC]DSA does not support encrypt */ + if (algid == KMF_ALGID_DSA || + algid == KMF_ALGID_SHA1WithDSA || + algid == KMF_ALGID_SHA256WithDSA || + algid == KMF_ALGID_SHA1WithECDSA || + algid == KMF_ALGID_SHA256WithECDSA || + algid == KMF_ALGID_SHA384WithECDSA || + algid == KMF_ALGID_SHA512WithECDSA || + algid == KMF_ALGID_NONE) { kmf_free_signed_cert(x509cert); free(x509cert); return (KMF_ERR_BAD_ALGORITHM); @@ -1186,8 +1176,9 @@ kmf_decrypt(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) AlgorithmId = x509_algoid_to_algid((KMF_OID *) &spki_ptr->algorithm.algorithm); - /* DSA does not support decrypt */ - if (AlgorithmId == KMF_ALGID_DSA) { + /* [EC]DSA does not support decrypt */ + if (AlgorithmId == KMF_ALGID_DSA || + AlgorithmId == KMF_ALGID_ECDSA) { ret = KMF_ERR_BAD_ALGORITHM; goto cleanup; } @@ -2991,12 +2982,26 @@ sign_cert(KMF_HANDLE_T handle, algid = x509_algoid_to_algid(signature_oid); - /* - * For DSA, KMF_SignDataWithKey() returns a 40-bytes decoded - * signature. So we must encode the signature correctly. - */ - if (algid == KMF_ALGID_SHA1WithDSA) { + if (algid == KMF_ALGID_SHA1WithECDSA || + algid == KMF_ALGID_SHA256WithECDSA || + algid == KMF_ALGID_SHA384WithECDSA || + algid == KMF_ALGID_SHA512WithECDSA) { + /* ASN.1 encode ECDSA signature */ + KMF_DATA signature; + + ret = DerEncodeECDSASignature(&signed_data, &signature); + kmf_free_data(&signed_data); + + if (ret != KMF_OK) + goto cleanup; + subj_cert->signature.encrypted = signature; + } else if (algid == KMF_ALGID_SHA1WithDSA || + algid == KMF_ALGID_SHA256WithDSA) { + /* + * For DSA, kmf_sign_data() returns a 40-byte + * signature. We must encode the signature correctly. + */ KMF_DATA signature; ret = DerEncodeDSASignature(&signed_data, &signature); @@ -3068,10 +3073,18 @@ verify_cert_with_key(KMF_HANDLE_T handle, if (algid == KMF_ALGID_NONE) return (KMF_ERR_BAD_ALGORITHM); - if (algid == KMF_ALGID_SHA1WithDSA) { + if (algid == KMF_ALGID_SHA1WithDSA || + algid == KMF_ALGID_SHA256WithDSA) { ret = DerDecodeDSASignature(&signed_data, &signature); if (ret != KMF_OK) goto cleanup; + } else if (algid == KMF_ALGID_SHA1WithECDSA || + algid == KMF_ALGID_SHA256WithECDSA || + algid == KMF_ALGID_SHA384WithECDSA || + algid == KMF_ALGID_SHA512WithECDSA) { + ret = DerDecodeECDSASignature(&signed_data, &signature); + if (ret != KMF_OK) + goto cleanup; } else { signature.Data = signed_data.Data; signature.Length = signed_data.Length; @@ -3091,7 +3104,12 @@ cleanup: kmf_free_signed_cert(signed_cert); free(signed_cert); } - if (algid == KMF_ALGID_SHA1WithDSA) { + if (algid == KMF_ALGID_SHA1WithDSA || + algid == KMF_ALGID_SHA256WithDSA || + algid == KMF_ALGID_SHA1WithECDSA || + algid == KMF_ALGID_SHA256WithECDSA || + algid == KMF_ALGID_SHA384WithECDSA || + algid == KMF_ALGID_SHA512WithECDSA) { free(signature.Data); } @@ -3149,27 +3167,39 @@ verify_cert_with_cert(KMF_HANDLE_T handle, /* Decode the to-be-verified cert so we know what algorithm to use */ ret = DerDecodeSignedCertificate(CertToBeVerifiedData, &ToBeVerifiedCert); - if (ret != KMF_OK) goto cleanup; algid = x509_algoid_to_algid(CERT_SIG_OID(ToBeVerifiedCert)); - if (algid == KMF_ALGID_SHA1WithDSA) { + if (algid == KMF_ALGID_SHA1WithDSA || + algid == KMF_ALGID_SHA256WithDSA) { ret = DerDecodeDSASignature(&signed_data, &signature); if (ret != KMF_OK) goto cleanup; + } else if (algid == KMF_ALGID_SHA1WithECDSA || + algid == KMF_ALGID_SHA256WithECDSA || + algid == KMF_ALGID_SHA384WithECDSA || + algid == KMF_ALGID_SHA512WithECDSA) { + ret = DerDecodeECDSASignature(&signed_data, &signature); + if (ret != KMF_OK) + goto cleanup; } else { signature.Data = signed_data.Data; signature.Length = signed_data.Length; } + ret = DerDecodeSignedCertificate(SignerCertData, &SignerCert); + if (ret != KMF_OK) + goto cleanup; + /* * Force use of PKCS11 API for kcfd/libelfsign. This is * required for the Cryptographic Framework's FIPS-140 boundary. */ - ret = plugin_verify_data_with_cert(handle, KMF_KEYSTORE_PK11TOKEN, - algid, &data_to_verify, &signature, SignerCertData); + ret = PKCS_VerifyData(handle, algid, + &SignerCert->certificate.subjectPublicKeyInfo, + &data_to_verify, &signature); cleanup: kmf_free_data(&data_to_verify); @@ -3185,7 +3215,12 @@ cleanup: free(ToBeVerifiedCert); } - if (algid == KMF_ALGID_SHA1WithDSA) { + if (algid == KMF_ALGID_SHA1WithDSA || + algid == KMF_ALGID_SHA256WithDSA || + algid == KMF_ALGID_SHA1WithECDSA || + algid == KMF_ALGID_SHA256WithECDSA || + algid == KMF_ALGID_SHA384WithECDSA || + algid == KMF_ALGID_SHA512WithECDSA) { free(signature.Data); } diff --git a/usr/src/lib/libkmf/libkmf/common/csrcrlop.c b/usr/src/lib/libkmf/libkmf/common/csrcrlop.c index 6c0f363157..165fce83d4 100644 --- a/usr/src/lib/libkmf/libkmf/common/csrcrlop.c +++ b/usr/src/lib/libkmf/libkmf/common/csrcrlop.c @@ -369,6 +369,7 @@ sign_csr(KMF_HANDLE_T handle, KMF_DATA signed_data = {0, NULL}; KMF_RETURN ret = KMF_OK; KMF_ATTRIBUTE attlist[5]; + KMF_ALGORITHM_INDEX algid; int i = 0; if (!SignedCsr) @@ -425,7 +426,29 @@ sign_csr(KMF_HANDLE_T handle, if (ret) goto cleanup; - subj_csr.signature.encrypted = signed_data; + algid = x509_algoid_to_algid(&algo->algorithm); + if (algid == KMF_ALGID_SHA1WithDSA || + algid == KMF_ALGID_SHA256WithDSA || + algid == KMF_ALGID_SHA1WithECDSA || + algid == KMF_ALGID_SHA256WithECDSA || + algid == KMF_ALGID_SHA384WithECDSA || + algid == KMF_ALGID_SHA512WithECDSA) { + /* + * For DSA and ECDSA, we must encode the + * signature correctly. + */ + KMF_DATA signature; + + ret = DerEncodeDSASignature(&signed_data, &signature); + kmf_free_data(&signed_data); + + if (ret != KMF_OK) + goto cleanup; + + subj_csr.signature.encrypted = signature; + } else { + subj_csr.signature.encrypted = signed_data; + } /* Now, re-encode the CSR with the new signature */ ret = DerEncodeSignedCsr(&subj_csr, SignedCsr); @@ -573,12 +596,43 @@ kmf_verify_csr(KMF_HANDLE_T handle, int numattr, x509alg = &csrdata->signature.algorithmIdentifier; algid = x509_algoid_to_algid(&x509alg->algorithm); + if (algid == KMF_ALGID_SHA1WithDSA || + algid == KMF_ALGID_SHA256WithDSA) { + /* Decode the DSA signature before verifying it */ + KMF_DATA signature; + rv = DerDecodeDSASignature(&csrdata->signature.encrypted, + &signature); + if (rv != KMF_OK) + goto end; + + rv = PKCS_VerifyData(handle, algid, + &csrdata->csr.subjectPublicKeyInfo, + &rawcsr, &signature); + + kmf_free_data(&signature); + } else if (algid == KMF_ALGID_SHA1WithECDSA || + algid == KMF_ALGID_SHA256WithECDSA || + algid == KMF_ALGID_SHA384WithECDSA || + algid == KMF_ALGID_SHA512WithECDSA) { + KMF_DATA signature; + rv = DerDecodeECDSASignature(&csrdata->signature.encrypted, + &signature); + if (rv != KMF_OK) + goto end; - rv = PKCS_VerifyData(handle, algid, - &csrdata->csr.subjectPublicKeyInfo, - &rawcsr, - &csrdata->signature.encrypted); + rv = PKCS_VerifyData(handle, algid, + &csrdata->csr.subjectPublicKeyInfo, + &rawcsr, &signature); + kmf_free_data(&signature); + } else { + rv = PKCS_VerifyData(handle, algid, + &csrdata->csr.subjectPublicKeyInfo, + &rawcsr, + &csrdata->signature.encrypted); + } + +end: kmf_free_data(&rawcsr); return (rv); } @@ -842,50 +896,3 @@ kmf_is_crl_file(KMF_HANDLE_T handle, char *filename, KMF_ENCODE_FORMAT *pformat) return (IsCRLFileFn(handle, filename, pformat)); } - -/* - * Phase 1 APIs still needed to maintain compat with elfsign. - */ -KMF_RETURN -KMF_CreateCSRFile(KMF_DATA *csrdata, KMF_ENCODE_FORMAT format, - char *csrfile) -{ - return (kmf_create_csr_file(csrdata, format, csrfile)); -} - -KMF_RETURN -KMF_SetCSRPubKey(KMF_HANDLE_T handle, - KMF_KEY_HANDLE *KMFKey, - KMF_CSR_DATA *Csr) -{ - return (kmf_set_csr_pubkey(handle, KMFKey, Csr)); -} - -KMF_RETURN -KMF_SetCSRVersion(KMF_CSR_DATA *CsrData, uint32_t version) -{ - return (kmf_set_csr_version(CsrData, version)); -} - -KMF_RETURN -KMF_SetCSRSignatureAlgorithm(KMF_CSR_DATA *CsrData, - KMF_ALGORITHM_INDEX sigAlg) -{ - return (kmf_set_csr_sig_alg(CsrData, sigAlg)); -} - -KMF_RETURN -KMF_SignCSR(KMF_HANDLE_T handle, - const KMF_CSR_DATA *tbsCsr, - KMF_KEY_HANDLE *Signkey, - KMF_DATA *SignedCsr) -{ - return (kmf_sign_csr(handle, tbsCsr, Signkey, SignedCsr)); -} - -KMF_RETURN -KMF_SetCSRSubjectName(KMF_CSR_DATA *CsrData, - KMF_X509_NAME *subject_name_ptr) -{ - return (kmf_set_csr_subject(CsrData, subject_name_ptr)); -} diff --git a/usr/src/lib/libkmf/libkmf/common/kmfoids.c b/usr/src/lib/libkmf/libkmf/common/kmfoids.c index a29ea9ee31..bc1eb3bf1a 100644 --- a/usr/src/lib/libkmf/libkmf/common/kmfoids.c +++ b/usr/src/lib/libkmf/libkmf/common/kmfoids.c @@ -1,13 +1,11 @@ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright(c) 1995-2000 Intel Corporation. All rights reserved. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <kmfapi.h> /* From X.520 */ @@ -363,6 +361,9 @@ OID_RSAEncryption[] = { OID_PKCS_1, 1 }, OID_MD2WithRSA[] = { OID_PKCS_1, 2 }, OID_MD5WithRSA[] = { OID_PKCS_1, 4 }, OID_SHA1WithRSA[] = { OID_PKCS_1, 5 }, +OID_SHA256WithRSA[] = { OID_PKCS_1, 11 }, +OID_SHA384WithRSA[] = { OID_PKCS_1, 12 }, +OID_SHA512WithRSA[] = { OID_PKCS_1, 13 }, OID_X9CM_DSA[] = { OID_X9CM_X9ALGORITHM, 1 }, OID_X9CM_DSAWithSHA1[] = { OID_X9CM_X9ALGORITHM, 3}; @@ -373,9 +374,10 @@ KMFOID_DSA = {OID_OIW_ALGORITHM_LENGTH+1, OID_OIW_DSA}, KMFOID_MD5WithRSA = {OID_PKCS_1_LENGTH+1, OID_MD5WithRSA}, KMFOID_MD2WithRSA = {OID_PKCS_1_LENGTH+1, OID_MD2WithRSA}, KMFOID_SHA1WithRSA = {OID_PKCS_1_LENGTH+1, OID_SHA1WithRSA}, -KMFOID_SHA1WithDSA = {OID_OIW_ALGORITHM_LENGTH+1, OID_OIW_DSAWithSHA1}, -KMFOID_OIW_DSAWithSHA1 = {OID_OIW_ALGORITHM_LENGTH+1, - OID_OIW_DSAWithSHA1}, +KMFOID_SHA256WithRSA = {OID_PKCS_1_LENGTH+1, OID_SHA256WithRSA}, +KMFOID_SHA384WithRSA = {OID_PKCS_1_LENGTH+1, OID_SHA384WithRSA}, +KMFOID_SHA512WithRSA = {OID_PKCS_1_LENGTH+1, OID_SHA512WithRSA}, +KMFOID_SHA1WithDSA = {OID_OIW_ALGORITHM_LENGTH+1, OID_OIW_DSAWithSHA1}, KMFOID_X9CM_DSA = {OID_X9CM_X9ALGORITHM_LENGTH+1, OID_X9CM_DSA}, KMFOID_X9CM_DSAWithSHA1 = {OID_X9CM_X9ALGORITHM_LENGTH+1, OID_X9CM_DSAWithSHA1}; @@ -400,3 +402,179 @@ KMFOID_MS_KP_SCLogon = {OID_MS_KP_SC_LOGON_LENGTH, OID_pkinit_kp_sc_logon}, KMFOID_MS_KP_SCLogon_UPN = {OID_MS_KP_SC_LOGON_UPN_LENGTH, OID_pkinit_san_upn}; + +/* + * MD5 + * iso(1) member-body(2) us(840) rsadsi(113549) + * digestAlgorithm(2) 5 + */ +#define RSADSI 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d +#define OID_id_md5 RSADSI, 0x02, 0x05 + +/* + * SHA2 OIDs + */ +#define NIST_ALG 96, 134, 72, 1, 101, 3, 4 +#define NIST_HASH NIST_ALG, 2 +#define OID_id_sha256 NIST_HASH, 1 +#define OID_id_sha384 NIST_HASH, 2 +#define OID_id_sha512 NIST_HASH, 3 +#define OID_id_sha224 NIST_HASH, 4 + +#define OID_id_dsa_with_sha224 NIST_ALG, 3, 1 +#define OID_id_dsa_with_sha256 NIST_ALG, 3, 2 + +/* + * For ECC support. + */ +#define CERTICOM_OID 0x2b, 0x81, 0x04 +#define SECG_OID CERTICOM_OID, 0x00 + +#define ANSI_X962_OID 0x2a, 0x86, 0x48, 0xce, 0x3d +#define ANSI_X962_CURVE_OID ANSI_X962_OID, 0x03 +#define ANSI_X962_GF2m_OID ANSI_X962_CURVE_OID, 0x00 +#define ANSI_X962_GFp_OID ANSI_X962_CURVE_OID, 0x01 + +#define ANSI_X962_SIG_OID ANSI_X962_OID, 0x04 +#define OID_ecdsa_with_sha224 ANSI_X962_SIG_OID, 3, 1 +#define OID_ecdsa_with_sha256 ANSI_X962_SIG_OID, 3, 2 +#define OID_ecdsa_with_sha384 ANSI_X962_SIG_OID, 3, 3 +#define OID_ecdsa_with_sha512 ANSI_X962_SIG_OID, 3, 4 + +static uint8_t +OID_secp112r1[] = { 0x6, 0x5, SECG_OID, 0x06 }, +OID_secp112r2[] = { 0x6, 0x5, SECG_OID, 0x07 }, +OID_secp128r1[] = { 0x6, 0x5, SECG_OID, 0x1c }, +OID_secp128r2[] = { 0x6, 0x5, SECG_OID, 0x1d }, +OID_secp160k1[] = { 0x6, 0x5, SECG_OID, 0x09 }, +OID_secp160r1[] = { 0x6, 0x5, SECG_OID, 0x08 }, +OID_secp160r2[] = { 0x6, 0x5, SECG_OID, 0x1e }, +OID_secp192k1[] = { 0x6, 0x5, SECG_OID, 0x1f }, +OID_secp224k1[] = { 0x6, 0x5, SECG_OID, 0x20 }, +OID_secp224r1[] = { 0x6, 0x5, SECG_OID, 0x21 }, +OID_secp256k1[] = { 0x6, 0x5, SECG_OID, 0x0a }, +OID_secp384r1[] = { 0x6, 0x5, SECG_OID, 0x22 }, +OID_secp521r1[] = { 0x6, 0x5, SECG_OID, 0x23 }, +OID_sect113r1[] = { 0x6, 0x5, SECG_OID, 0x04 }, +OID_sect113r2[] = { 0x6, 0x5, SECG_OID, 0x05 }, +OID_sect131r1[] = { 0x6, 0x5, SECG_OID, 0x16 }, +OID_sect131r2[] = { 0x6, 0x5, SECG_OID, 0x17 }, +OID_sect163k1[] = { 0x6, 0x5, SECG_OID, 0x01 }, +OID_sect163r1[] = { 0x6, 0x5, SECG_OID, 0x02 }, +OID_sect163r2[] = { 0x6, 0x5, SECG_OID, 0x0f }, +OID_sect193r1[] = { 0x6, 0x5, SECG_OID, 0x18 }, +OID_sect193r2[] = { 0x6, 0x5, SECG_OID, 0x19 }, +OID_sect233k1[] = { 0x6, 0x5, SECG_OID, 0x1a }, +OID_sect233r1[] = { 0x6, 0x5, SECG_OID, 0x1b }, +OID_sect239k1[] = { 0x6, 0x5, SECG_OID, 0x03 }, +OID_sect283k1[] = { 0x6, 0x5, SECG_OID, 0x10 }, +OID_sect283r1[] = { 0x6, 0x5, SECG_OID, 0x11 }, +OID_sect409k1[] = { 0x6, 0x5, SECG_OID, 0x24 }, +OID_sect409r1[] = { 0x6, 0x5, SECG_OID, 0x25 }, +OID_sect571k1[] = { 0x6, 0x5, SECG_OID, 0x26 }, +OID_sect571r1[] = { 0x6, 0x5, SECG_OID, 0x27 }, +OID_c2pnb163v1[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x01 }, +OID_c2pnb163v2[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x02 }, +OID_c2pnb163v3[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x03 }, +OID_c2pnb176v1[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x04 }, +OID_c2tnb191v1[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x05 }, +OID_c2tnb191v2[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x06 }, +OID_c2tnb191v3[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x07 }, +OID_c2pnb208w1[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x0a }, +OID_c2tnb239v1[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x0b }, +OID_c2tnb239v2[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x0c }, +OID_c2tnb239v3[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x0d }, +OID_c2pnb272w1[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x10 }, +OID_c2pnb304w1[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x11 }, +OID_c2tnb359v1[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x12 }, +OID_c2pnb368w1[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x13 }, +OID_c2tnb431r1[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x14 }, + +OID_prime192v2[] = { 0x6, 0x8, ANSI_X962_GFp_OID, 0x02 }, +OID_prime192v3[] = { 0x6, 0x8, ANSI_X962_GFp_OID, 0x03 }, + +OID_secp192r1[] = { 0x6, 0x8, ANSI_X962_GFp_OID, 0x01 }, +OID_secp256r1[] = { 0x6, 0x8, ANSI_X962_GFp_OID, 0x07 }; + +const KMF_OID +KMFOID_ECC_secp112r1 = {sizeof (OID_secp112r1), OID_secp112r1}, +KMFOID_ECC_secp112r2 = {sizeof (OID_secp112r2), OID_secp112r2}, +KMFOID_ECC_secp128r1 = {sizeof (OID_secp128r1), OID_secp128r1}, +KMFOID_ECC_secp128r2 = {sizeof (OID_secp128r2), OID_secp128r2}, +KMFOID_ECC_secp160k1 = {sizeof (OID_secp160k1), OID_secp160k1}, +KMFOID_ECC_secp160r1 = {sizeof (OID_secp160r1), OID_secp160r1}, +KMFOID_ECC_secp160r2 = {sizeof (OID_secp160r2), OID_secp160r2}, +KMFOID_ECC_secp192k1 = {sizeof (OID_secp192k1), OID_secp192k1}, +KMFOID_ECC_secp224k1 = {sizeof (OID_secp224k1), OID_secp224k1}, +KMFOID_ECC_secp224r1 = {sizeof (OID_secp224r1), OID_secp224r1}, +KMFOID_ECC_secp256k1 = {sizeof (OID_secp256k1), OID_secp256k1}, +KMFOID_ECC_secp384r1 = {sizeof (OID_secp384r1), OID_secp384r1}, +KMFOID_ECC_secp521r1 = {sizeof (OID_secp521r1), OID_secp521r1}, +KMFOID_ECC_sect113r1 = {sizeof (OID_sect113r1), OID_sect113r1}, +KMFOID_ECC_sect113r2 = {sizeof (OID_sect113r2), OID_sect113r2}, +KMFOID_ECC_sect131r1 = {sizeof (OID_sect131r1), OID_sect131r1}, +KMFOID_ECC_sect131r2 = {sizeof (OID_sect131r2), OID_sect131r2}, +KMFOID_ECC_sect163k1 = {sizeof (OID_sect163k1), OID_sect163k1}, +KMFOID_ECC_sect163r1 = {sizeof (OID_sect163r1), OID_sect163r1}, +KMFOID_ECC_sect163r2 = {sizeof (OID_sect163r2), OID_sect163r2}, +KMFOID_ECC_sect193r1 = {sizeof (OID_sect193r1), OID_sect193r1}, +KMFOID_ECC_sect193r2 = {sizeof (OID_sect193r2), OID_sect193r2}, +KMFOID_ECC_sect233k1 = {sizeof (OID_sect233k1), OID_sect233k1}, +KMFOID_ECC_sect233r1 = {sizeof (OID_sect233r1), OID_sect233r1}, +KMFOID_ECC_sect239k1 = {sizeof (OID_sect239k1), OID_sect239k1}, +KMFOID_ECC_sect283k1 = {sizeof (OID_sect283k1), OID_sect283k1}, +KMFOID_ECC_sect283r1 = {sizeof (OID_sect283r1), OID_sect283r1}, +KMFOID_ECC_sect409k1 = {sizeof (OID_sect409k1), OID_sect409k1}, +KMFOID_ECC_sect409r1 = {sizeof (OID_sect409r1), OID_sect409r1}, +KMFOID_ECC_sect571k1 = {sizeof (OID_sect571k1), OID_sect571k1}, +KMFOID_ECC_sect571r1 = {sizeof (OID_sect571r1), OID_sect571r1}, +KMFOID_ECC_c2pnb163v1 = {sizeof (OID_c2pnb163v1), OID_c2pnb163v1}, +KMFOID_ECC_c2pnb163v2 = {sizeof (OID_c2pnb163v2), OID_c2pnb163v2}, +KMFOID_ECC_c2pnb163v3 = {sizeof (OID_c2pnb163v3), OID_c2pnb163v3}, +KMFOID_ECC_c2pnb176v1 = {sizeof (OID_c2pnb176v1), OID_c2pnb176v1}, +KMFOID_ECC_c2tnb191v1 = {sizeof (OID_c2tnb191v1), OID_c2tnb191v1}, +KMFOID_ECC_c2tnb191v2 = {sizeof (OID_c2tnb191v2), OID_c2tnb191v2}, +KMFOID_ECC_c2tnb191v3 = {sizeof (OID_c2tnb191v3), OID_c2tnb191v3}, +KMFOID_ECC_c2pnb208w1 = {sizeof (OID_c2pnb208w1), OID_c2pnb208w1}, +KMFOID_ECC_c2tnb239v1 = {sizeof (OID_c2tnb239v1), OID_c2tnb239v1}, +KMFOID_ECC_c2tnb239v2 = {sizeof (OID_c2tnb239v2), OID_c2tnb239v2}, +KMFOID_ECC_c2tnb239v3 = {sizeof (OID_c2tnb239v3), OID_c2tnb239v3}, +KMFOID_ECC_c2pnb272w1 = {sizeof (OID_c2pnb272w1), OID_c2pnb272w1}, +KMFOID_ECC_c2pnb304w1 = {sizeof (OID_c2pnb304w1), OID_c2pnb304w1}, +KMFOID_ECC_c2tnb359v1 = {sizeof (OID_c2tnb359v1), OID_c2tnb359v1}, +KMFOID_ECC_c2pnb368w1 = {sizeof (OID_c2pnb368w1), OID_c2pnb368w1}, +KMFOID_ECC_c2tnb431r1 = {sizeof (OID_c2tnb431r1), OID_c2tnb431r1}, +KMFOID_ECC_prime192v2 = {sizeof (OID_prime192v2), OID_prime192v2}, +KMFOID_ECC_prime192v3 = {sizeof (OID_prime192v3), OID_prime192v3}, +KMFOID_ECC_secp192r1 = {sizeof (OID_secp192r1), OID_secp192r1}, +KMFOID_ECC_secp256r1 = {sizeof (OID_secp256r1), OID_secp256r1}; + +static uint8_t +OID_EC_PUBLIC_KEY[] = {ANSI_X962_OID, 0x02, 0x01}, +OID_ECDSA_SHA1[] = {ANSI_X962_OID, 0x04, 0x01}, +OID_ECDSA_SHA224[] = {ANSI_X962_OID, 0x04, 0x03, 0x01}, +OID_ECDSA_SHA256[] = {ANSI_X962_OID, 0x04, 0x03, 0x02}, +OID_ECDSA_SHA384[] = {ANSI_X962_OID, 0x04, 0x03, 0x03}, +OID_ECDSA_SHA512[] = {ANSI_X962_OID, 0x04, 0x03, 0x04}, +OID_DSA_SHA224[] = {OID_id_dsa_with_sha224}, +OID_DSA_SHA256[] = {OID_id_dsa_with_sha256}, +OID_SHA224[] = {OID_id_sha224}, +OID_SHA256[] = {OID_id_sha256}, +OID_SHA384[] = {OID_id_sha384}, +OID_SHA512[] = {OID_id_sha512}, +OID_MD5[] = {OID_id_md5}; + +const KMF_OID +KMFOID_EC_PUBLIC_KEY = { sizeof (OID_EC_PUBLIC_KEY), OID_EC_PUBLIC_KEY}, +KMFOID_SHA1WithECDSA = { sizeof (OID_ECDSA_SHA1), OID_ECDSA_SHA1}, +KMFOID_SHA224WithECDSA = { sizeof (OID_ECDSA_SHA224), OID_ECDSA_SHA224}, +KMFOID_SHA256WithECDSA = { sizeof (OID_ECDSA_SHA256), OID_ECDSA_SHA256}, +KMFOID_SHA384WithECDSA = { sizeof (OID_ECDSA_SHA384), OID_ECDSA_SHA384}, +KMFOID_SHA512WithECDSA = { sizeof (OID_ECDSA_SHA512), OID_ECDSA_SHA512}, +KMFOID_SHA224WithDSA = { sizeof (OID_DSA_SHA224), OID_DSA_SHA224}, +KMFOID_SHA256WithDSA = { sizeof (OID_DSA_SHA256), OID_DSA_SHA256}, +KMFOID_SHA224 = { sizeof (OID_SHA224), OID_SHA224}, +KMFOID_SHA256 = { sizeof (OID_SHA256), OID_SHA256}, +KMFOID_SHA384 = { sizeof (OID_SHA384), OID_SHA384}, +KMFOID_SHA512 = { sizeof (OID_SHA512), OID_SHA512}, +KMFOID_MD5 = { sizeof (OID_MD5), OID_MD5}; diff --git a/usr/src/lib/libkmf/libkmf/common/mapfile-vers b/usr/src/lib/libkmf/libkmf/common/mapfile-vers index f1d5b722df..d221e5b79d 100644 --- a/usr/src/lib/libkmf/libkmf/common/mapfile-vers +++ b/usr/src/lib/libkmf/libkmf/common/mapfile-vers @@ -75,6 +75,58 @@ SUNW_1.1 { KMFOID_Description; KMFOID_DestinationIndicator; KMFOID_DistinguishedName; + KMFOID_EC_PUBLIC_KEY; + KMFOID_ECC_c2pnb163v1; + KMFOID_ECC_c2pnb163v2; + KMFOID_ECC_c2pnb163v3; + KMFOID_ECC_c2pnb176v1; + KMFOID_ECC_c2pnb208w1; + KMFOID_ECC_c2pnb272w1; + KMFOID_ECC_c2pnb304w1; + KMFOID_ECC_c2pnb368w1; + KMFOID_ECC_c2tnb191v1; + KMFOID_ECC_c2tnb191v2; + KMFOID_ECC_c2tnb191v3; + KMFOID_ECC_c2tnb239v1; + KMFOID_ECC_c2tnb239v2; + KMFOID_ECC_c2tnb239v3; + KMFOID_ECC_c2tnb359v1; + KMFOID_ECC_c2tnb431r1; + KMFOID_ECC_prime192v2; + KMFOID_ECC_prime192v3; + KMFOID_ECC_secp112r1; + KMFOID_ECC_secp112r2; + KMFOID_ECC_secp128r1; + KMFOID_ECC_secp128r2; + KMFOID_ECC_secp160k1; + KMFOID_ECC_secp160r1; + KMFOID_ECC_secp160r2; + KMFOID_ECC_secp192k1; + KMFOID_ECC_secp224k1; + KMFOID_ECC_secp224r1; + KMFOID_ECC_secp256k1; + KMFOID_ECC_secp384r1; + KMFOID_ECC_secp521r1; + KMFOID_ECC_sect113r1; + KMFOID_ECC_sect113r2; + KMFOID_ECC_sect131r1; + KMFOID_ECC_sect131r2; + KMFOID_ECC_sect163k1; + KMFOID_ECC_sect163r1; + KMFOID_ECC_sect163r2; + KMFOID_ECC_sect193r1; + KMFOID_ECC_sect193r2; + KMFOID_ECC_sect233k1; + KMFOID_ECC_sect233r1; + KMFOID_ECC_sect239k1; + KMFOID_ECC_sect283k1; + KMFOID_ECC_sect283r1; + KMFOID_ECC_sect409k1; + KMFOID_ECC_sect409r1; + KMFOID_ECC_sect571k1; + KMFOID_ECC_sect571r1; + KMFOID_ECC_secp192r1; + KMFOID_ECC_secp256r1; KMFOID_EmailAddress; KMFOID_EnhancedSearchGuide; KMFOID_ExtendedCertificateAttributes; @@ -95,6 +147,7 @@ SUNW_1.1 { KMFOID_KnowledgeInformation; KMFOID_LocalityName; KMFOID_MD2WithRSA; + KMFOID_MD5; KMFOID_MD5WithRSA; KMFOID_Member; KMFOID_MessageDigest; @@ -102,7 +155,6 @@ SUNW_1.1 { KMFOID_MS_KP_SCLogon_UPN; KMFOID_Name; KMFOID_NameConstraints; - KMFOID_OIW_DSAWithSHA1; KMFOID_ObjectClass; KMFOID_OrganizationName; KMFOID_OrganizationalUnitName; @@ -139,7 +191,21 @@ SUNW_1.1 { KMFOID_RoleOccupant; KMFOID_SHA1; KMFOID_SHA1WithDSA; + KMFOID_SHA1WithECDSA; KMFOID_SHA1WithRSA; + KMFOID_SHA224; + KMFOID_SHA256; + KMFOID_SHA384; + KMFOID_SHA512; + KMFOID_SHA224WithDSA; + KMFOID_SHA256WithDSA; + KMFOID_SHA224WithECDSA; + KMFOID_SHA256WithECDSA; + KMFOID_SHA256WithRSA; + KMFOID_SHA384WithECDSA; + KMFOID_SHA384WithRSA; + KMFOID_SHA512WithECDSA; + KMFOID_SHA512WithRSA; KMFOID_SearchGuide; KMFOID_SeeAlso; KMFOID_SerialNumber; @@ -323,10 +389,12 @@ SUNWprivate_1.1 { free_entrylist; get_entrylist; kmf_select_token; + kmf_create_pk11_session; parsePolicyElement; - PKCS_AcquirePublicKeyHandle; - PKCS_GetDefaultSignatureMode; - pkcs_get_alg_map; + PKCS_VerifyData; + PKCS_DigestData; + PKCS_EncryptData; + get_pk11_data; x509_algid_to_algoid; x509_algoid_to_algid; local: diff --git a/usr/src/lib/libkmf/libkmf/common/pk11keys.c b/usr/src/lib/libkmf/libkmf/common/pk11keys.c index 5a6e945009..df2cd0f8df 100644 --- a/usr/src/lib/libkmf/libkmf/common/pk11keys.c +++ b/usr/src/lib/libkmf/libkmf/common/pk11keys.c @@ -1,26 +1,91 @@ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (c) 1995-2000 Intel Corporation. All rights reserved. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <kmfapiP.h> #include <sha1.h> #include <security/cryptoki.h> -#include <algorithm.h> #include <ber_der.h> #define MAX_PUBLIC_KEY_TEMPLATES (20) #define MAX_PRIVATE_KEY_TEMPLATES (24) #define MAX_SECRET_KEY_TEMPLATES (24) -static KMF_RETURN -create_pk11_session(CK_SESSION_HANDLE *sessionp, CK_MECHANISM_TYPE wanted_mech, +typedef struct +{ + KMF_ALGORITHM_INDEX kmfAlgorithmId; + CK_KEY_TYPE ckKeyType; + CK_MECHANISM_TYPE signmech; + CK_MECHANISM_TYPE vfymech; + CK_MECHANISM_TYPE hashmech; +} ALG_INFO; + +static const ALG_INFO alg_info_map[] = { + { KMF_ALGID_RSA, CKK_RSA, CKM_RSA_PKCS, CKM_RSA_PKCS, NULL}, + { KMF_ALGID_DSA, CKK_DSA, CKM_DSA, CKM_DSA, CKM_SHA_1 }, + { KMF_ALGID_ECDSA, CKK_EC, CKM_ECDSA, CKM_ECDSA, CKM_SHA_1 }, + { KMF_ALGID_SHA1WithDSA, CKK_DSA, CKM_DSA, CKM_DSA, CKM_SHA_1 }, + { KMF_ALGID_SHA256WithDSA, CKK_DSA, CKM_DSA, CKM_DSA, CKM_SHA256 }, + + /* + * For RSA, the verify can be done using a single mechanism, + * but signing must be done separately because not all hardware + * tokens support the combined hash+key operations. + */ + { KMF_ALGID_MD5WithRSA, CKK_RSA, CKM_RSA_PKCS, + CKM_MD5_RSA_PKCS, CKM_MD5}, + { KMF_ALGID_SHA1WithRSA, CKK_RSA, CKM_RSA_PKCS, + CKM_SHA1_RSA_PKCS, CKM_SHA_1}, + { KMF_ALGID_SHA256WithRSA, CKK_RSA, CKM_RSA_PKCS, + CKM_SHA256_RSA_PKCS, CKM_SHA256}, + { KMF_ALGID_SHA384WithRSA, CKK_RSA, CKM_RSA_PKCS, + CKM_SHA384_RSA_PKCS, CKM_SHA384}, + { KMF_ALGID_SHA512WithRSA, CKK_RSA, CKM_RSA_PKCS, + CKM_SHA512_RSA_PKCS, CKM_SHA512}, + { KMF_ALGID_SHA1WithECDSA, CKK_EC, CKM_ECDSA, + CKM_ECDSA, CKM_SHA_1}, + { KMF_ALGID_SHA256WithECDSA, CKK_EC, CKM_ECDSA, + CKM_ECDSA, CKM_SHA256}, + { KMF_ALGID_SHA384WithECDSA, CKK_EC, CKM_ECDSA, + CKM_ECDSA, CKM_SHA384}, + { KMF_ALGID_SHA512WithECDSA, CKK_EC, CKM_ECDSA, + CKM_ECDSA, CKM_SHA512} +}; + +KMF_RETURN +get_pk11_data(KMF_ALGORITHM_INDEX AlgId, + CK_KEY_TYPE *keytype, CK_MECHANISM_TYPE *signmech, + CK_MECHANISM_TYPE *hashmech, boolean_t vfy) +{ + uint32_t uIndex; + uint32_t uMapSize = + sizeof (alg_info_map) / sizeof (ALG_INFO); + + for (uIndex = 0; uIndex < uMapSize; uIndex++) { + if (alg_info_map[uIndex].kmfAlgorithmId == AlgId) { + if (keytype) + *keytype = alg_info_map[uIndex].ckKeyType; + if (hashmech) + *hashmech = alg_info_map[uIndex].hashmech; + if (signmech) + *signmech = + (vfy ? alg_info_map[uIndex].vfymech : + alg_info_map[uIndex].signmech); + return (KMF_OK); + } + } + /* no match */ + return (KMF_ERR_BAD_ALGORITHM); +} + +KMF_RETURN +kmf_create_pk11_session(CK_SESSION_HANDLE *sessionp, + CK_MECHANISM_TYPE wanted_mech, CK_FLAGS wanted_flags) { CK_RV rv; @@ -56,7 +121,8 @@ create_pk11_session(CK_SESSION_HANDLE *sessionp, CK_MECHANISM_TYPE wanted_mech, for (i = 0; i < pulCount; i++) { rv = C_GetMechanismInfo(pSlotList[i], wanted_mech, &info); - if (rv == CKR_OK && (info.flags & wanted_flags)) + if (rv == CKR_OK && + (info.flags & wanted_flags) == wanted_flags) break; } if (i < pulCount) { @@ -173,7 +239,7 @@ PKCS_CreatePublicKey( } /* Fill in the common key attributes */ - if (!pkcs_algid_to_keytype(AlgorithmId, &ckKeyType)) { + if (get_pk11_data(AlgorithmId, &ckKeyType, NULL, NULL, 0)) { goto cleanup; } if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, @@ -210,6 +276,7 @@ PKCS_CreatePublicKey( MAX_PUBLIC_KEY_TEMPLATES, CKA_MODULUS, (CK_BYTE *)KeyParts[KMF_RSA_MODULUS].Data, (CK_ULONG)KeyParts[KMF_RSA_MODULUS].Length) || + !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, MAX_PUBLIC_KEY_TEMPLATES, CKA_PUBLIC_EXPONENT, (CK_BYTE *)KeyParts[KMF_RSA_PUBLIC_EXPONENT].Data, @@ -239,6 +306,20 @@ PKCS_CreatePublicKey( goto cleanup; } break; + case CKK_EC: + if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, + MAX_PUBLIC_KEY_TEMPLATES, CKA_EC_POINT, + (CK_BYTE *)KeyParts[KMF_ECDSA_POINT].Data, + (CK_ULONG)KeyParts[KMF_ECDSA_POINT].Length) || + + !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, + MAX_PUBLIC_KEY_TEMPLATES, CKA_EC_PARAMS, + (CK_BYTE *)KeyParts[KMF_ECDSA_PARAMS].Data, + (CK_ULONG)KeyParts[KMF_ECDSA_PARAMS].Length)) { + mrReturn = KMF_ERR_INTERNAL; + goto cleanup; + } + break; default: mrReturn = KMF_ERR_BAD_PARAMETER; } @@ -274,18 +355,16 @@ cleanup: * - Public Key with label: * Attempts to find a public key with the corresponding label. */ -KMF_RETURN +static KMF_RETURN PKCS_AcquirePublicKeyHandle(CK_SESSION_HANDLE ckSession, const KMF_X509_SPKI *pKey, CK_KEY_TYPE ckRequestedKeyType, - CK_OBJECT_HANDLE *pckKeyHandle, - KMF_BOOL *pbTemporary) + CK_OBJECT_HANDLE *pckKeyHandle) { KMF_RETURN mrReturn = KMF_OK; - /* Key searching variables */ - CK_OBJECT_HANDLE ckKeyHandle; + CK_OBJECT_HANDLE ckKeyHandle = 0; CK_OBJECT_CLASS ckObjClass; CK_KEY_TYPE ckKeyType; CK_ATTRIBUTE ckTemplate[3]; @@ -299,8 +378,6 @@ PKCS_AcquirePublicKeyHandle(CK_SESSION_HANDLE ckSession, if (mrReturn != KMF_OK) return (mrReturn); - *pbTemporary = KMF_TRUE; - /* Fetch the key class and algorithm from the object */ ckNumTemplates = 0; if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, @@ -309,21 +386,20 @@ PKCS_AcquirePublicKeyHandle(CK_SESSION_HANDLE ckSession, !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, ckMaxTemplates, CKA_KEY_TYPE, (CK_BYTE *)&ckKeyType, sizeof (ckKeyType))) { + (void) C_DestroyObject(ckSession, ckKeyHandle); return (KMF_ERR_INTERNAL); } ckRv = C_GetAttributeValue(ckSession, ckKeyHandle, ckTemplate, ckNumTemplates); if (ckRv != CKR_OK) { + (void) C_DestroyObject(ckSession, ckKeyHandle); return (ckRv); } /* Make sure the results match the expected values */ if ((ckKeyType != ckRequestedKeyType) || (ckObjClass != CKO_PUBLIC_KEY)) { - if (*pbTemporary == KMF_TRUE) { - (void) C_DestroyObject(ckSession, ckKeyHandle); - } - + (void) C_DestroyObject(ckSession, ckKeyHandle); return (KMF_ERR_BAD_KEY_FORMAT); } @@ -333,95 +409,136 @@ PKCS_AcquirePublicKeyHandle(CK_SESSION_HANDLE ckSession, return (KMF_OK); } -KMF_SIGNATURE_MODE -PKCS_GetDefaultSignatureMode(KMF_ALGORITHM_INDEX AlgId) -{ - KMF_SIGNATURE_MODE AlgMode; - - switch (AlgId) { - case KMF_ALGID_RSA: - case KMF_ALGID_MD5WithRSA: - case KMF_ALGID_MD2WithRSA: - case KMF_ALGID_SHA1WithRSA: - AlgMode = KMF_ALGMODE_PKCS1_EMSA_V15; - break; - default: - AlgMode = KMF_ALGMODE_NONE; - break; - } - - return (AlgMode); -} - +/* + * Utility routine for verifying generic data using + * the cryptographic framework (PKCS#11). + * There are situations where we want to force this + * operation to happen in a specific keystore. + * For example: + * libelfsign.so.1 verifies signatures on crypto libraries. + * We must use pkcs11 functions to verify the pkcs11 + * plugins in order to keep the validation within the + * Cryptographic Framework's FIPS-140 boundary. To avoid + * a circular dependency, pksc11_softtoken.so.1 is + * interposed by libkcfd.so.1 via kcfd, which prevents + * libpkcs11.so.1's interfaces from being used when libkmf.so.1 + * is called from kcfd. + * + * This also saves code and time because verify operations + * only use public keys and do not need acccess to any + * keystore specific functions. + */ KMF_RETURN -PKCS_VerifyData(KMF_HANDLE_T kmfh, +PKCS_VerifyData(KMF_HANDLE_T handle, KMF_ALGORITHM_INDEX AlgorithmId, KMF_X509_SPKI *keyp, KMF_DATA *data, - KMF_DATA *signed_data) + KMF_DATA *signature) { - KMF_RETURN rv = KMF_OK; - PKCS_ALGORITHM_MAP *pAlgMap = NULL; - CK_RV ckRv; - CK_MECHANISM ckMechanism; - CK_OBJECT_HANDLE ckKeyHandle; - KMF_BOOL bTempKey; + KMF_RETURN rv = KMF_OK; + CK_RV ckRv; + KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; + CK_MECHANISM ckMechanism; + CK_MECHANISM_TYPE mechtype, hashmech; + CK_OBJECT_HANDLE ckKeyHandle = 0; + CK_KEY_TYPE pk11keytype; CK_SESSION_HANDLE ckSession = 0; + CK_ATTRIBUTE subprime = { CKA_SUBPRIME, NULL, 0 }; + CK_BYTE *dataptr; + CK_ULONG datalen; + KMF_DATA hashData = {NULL, 0}; + uchar_t digest[1024]; if (AlgorithmId == KMF_ALGID_NONE) return (KMF_ERR_BAD_ALGORITHM); - pAlgMap = pkcs_get_alg_map(KMF_ALGCLASS_SIGNATURE, - AlgorithmId, PKCS_GetDefaultSignatureMode(AlgorithmId)); - - if (!pAlgMap) + if (get_pk11_data(AlgorithmId, &pk11keytype, &mechtype, &hashmech, 1)) return (KMF_ERR_BAD_ALGORITHM); - rv = create_pk11_session(&ckSession, pAlgMap->pkcs_mechanism, - CKF_VERIFY); - + /* + * Verify in metaslot/softtoken since only the public key is needed + * and not all hardware tokens support the combined [hash]-RSA/DSA/EC + * mechanisms. + */ + rv = kmf_create_pk11_session(&ckSession, mechtype, 0); if (rv != KMF_OK) return (rv); /* Fetch the verifying key */ rv = PKCS_AcquirePublicKeyHandle(ckSession, keyp, - pAlgMap->key_type, &ckKeyHandle, &bTempKey); + pk11keytype, &ckKeyHandle); if (rv != KMF_OK) { (void) C_CloseSession(ckSession); return (rv); } + dataptr = data->Data; + datalen = data->Length; + /* + * For some mechanisms, we must compute the hash separately + * and then do the verify. + */ + if (hashmech != 0 && + (mechtype == CKM_ECDSA || + mechtype == CKM_DSA || + mechtype == CKM_RSA_PKCS)) { + hashData.Data = digest; + hashData.Length = sizeof (digest); + + rv = PKCS_DigestData(handle, ckSession, + hashmech, data, &hashData, + (mechtype == CKM_RSA_PKCS)); + if (rv) + goto cleanup; - ckMechanism.mechanism = pAlgMap->pkcs_mechanism; + dataptr = hashData.Data; + datalen = hashData.Length; + } + if (mechtype == CKM_DSA && + hashmech == CKM_SHA256) { + /* + * FIPS 186-3 says that when using DSA + * the hash must be truncated to the size of the + * subprime. + */ + ckRv = C_GetAttributeValue(ckSession, + ckKeyHandle, &subprime, 1); + if (ckRv != CKR_OK) { + kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; + kmfh->lasterr.errcode = ckRv; + rv = KMF_ERR_INTERNAL; + goto cleanup; + } + datalen = subprime.ulValueLen; + } + + ckMechanism.mechanism = mechtype; ckMechanism.pParameter = NULL; ckMechanism.ulParameterLen = 0; ckRv = C_VerifyInit(ckSession, &ckMechanism, ckKeyHandle); if (ckRv != CKR_OK) { - if (bTempKey) - (void) C_DestroyObject(ckSession, ckKeyHandle); kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; kmfh->lasterr.errcode = ckRv; - (void) C_CloseSession(ckSession); - return (KMF_ERR_INTERNAL); + rv = KMF_ERR_INTERNAL; + goto cleanup; } - - ckRv = C_Verify(ckSession, (CK_BYTE *)data->Data, - (CK_ULONG)data->Length, - (CK_BYTE *)signed_data->Data, - (CK_ULONG)signed_data->Length); + ckRv = C_Verify(ckSession, + dataptr, datalen, + (CK_BYTE *)signature->Data, + (CK_ULONG)signature->Length); if (ckRv != CKR_OK) { kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; kmfh->lasterr.errcode = ckRv; rv = KMF_ERR_INTERNAL; } - if (bTempKey) - (void) C_DestroyObject(ckSession, ckKeyHandle); +cleanup: + if (ckKeyHandle != 0) + (void) C_DestroyObject(ckSession, ckKeyHandle); (void) C_CloseSession(ckSession); return (rv); - } KMF_RETURN @@ -432,11 +549,11 @@ PKCS_EncryptData(KMF_HANDLE_T kmfh, KMF_DATA *ciphertext) { KMF_RETURN rv = KMF_OK; - PKCS_ALGORITHM_MAP *pAlgMap = NULL; CK_RV ckRv; CK_MECHANISM ckMechanism; - CK_OBJECT_HANDLE ckKeyHandle; - KMF_BOOL bTempKey; + CK_MECHANISM_TYPE mechtype; + CK_KEY_TYPE keytype; + CK_OBJECT_HANDLE ckKeyHandle = 0; CK_SESSION_HANDLE ckSession = NULL; CK_ULONG out_len = 0, in_len = 0, total_encrypted = 0; uint8_t *in_data, *out_data; @@ -446,21 +563,16 @@ PKCS_EncryptData(KMF_HANDLE_T kmfh, CK_ULONG ckMaxTemplates = (sizeof (ckTemplate) / sizeof (CK_ATTRIBUTE)); - pAlgMap = pkcs_get_alg_map(KMF_ALGCLASS_SIGNATURE, - AlgorithmId, PKCS_GetDefaultSignatureMode(AlgorithmId)); - - if (!pAlgMap) + if (get_pk11_data(AlgorithmId, &keytype, &mechtype, NULL, 0)) return (KMF_ERR_BAD_ALGORITHM); - rv = create_pk11_session(&ckSession, pAlgMap->pkcs_mechanism, - CKF_ENCRYPT); - + rv = kmf_create_pk11_session(&ckSession, mechtype, CKF_ENCRYPT); if (rv != KMF_OK) return (rv); /* Get the public key used in encryption */ rv = PKCS_AcquirePublicKeyHandle(ckSession, keyp, - pAlgMap->key_type, &ckKeyHandle, &bTempKey); + keytype, &ckKeyHandle); if (rv != KMF_OK) { (void) C_CloseSession(ckSession); @@ -471,7 +583,7 @@ PKCS_EncryptData(KMF_HANDLE_T kmfh, ckNumTemplates = 0; if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, ckMaxTemplates, CKA_MODULUS, (CK_BYTE *)NULL, sizeof (CK_ULONG))) { - if (bTempKey) + if (ckKeyHandle != 0) (void) C_DestroyObject(ckSession, ckKeyHandle); (void) C_CloseSession(ckSession); return (KMF_ERR_INTERNAL); @@ -481,7 +593,7 @@ PKCS_EncryptData(KMF_HANDLE_T kmfh, ckTemplate, ckNumTemplates); if (ckRv != CKR_OK) { - if (bTempKey) + if (ckKeyHandle != 0) (void) C_DestroyObject(ckSession, ckKeyHandle); kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; kmfh->lasterr.errcode = ckRv; @@ -491,13 +603,13 @@ PKCS_EncryptData(KMF_HANDLE_T kmfh, out_len = ckTemplate[0].ulValueLen; if (out_len > ciphertext->Length) { - if (bTempKey) + if (ckKeyHandle != 0) (void) C_DestroyObject(ckSession, ckKeyHandle); (void) C_CloseSession(ckSession); return (KMF_ERR_BUFFER_SIZE); } - ckMechanism.mechanism = pAlgMap->pkcs_mechanism; + ckMechanism.mechanism = mechtype; ckMechanism.pParameter = NULL_PTR; ckMechanism.ulParameterLen = 0; @@ -512,7 +624,7 @@ PKCS_EncryptData(KMF_HANDLE_T kmfh, for (i = 0; i < blocks; i++) { ckRv = C_EncryptInit(ckSession, &ckMechanism, ckKeyHandle); if (ckRv != CKR_OK) { - if (bTempKey) + if (ckKeyHandle != 0) (void) C_DestroyObject(ckSession, ckKeyHandle); kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; kmfh->lasterr.errcode = ckRv; @@ -523,7 +635,7 @@ PKCS_EncryptData(KMF_HANDLE_T kmfh, (CK_BYTE_PTR)out_data, &out_len); if (ckRv != CKR_OK) { - if (bTempKey) + if (ckKeyHandle != 0) (void) C_DestroyObject(ckSession, ckKeyHandle); kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; kmfh->lasterr.errcode = ckRv; @@ -540,7 +652,7 @@ PKCS_EncryptData(KMF_HANDLE_T kmfh, /* Encrypt the remaining data */ ckRv = C_EncryptInit(ckSession, &ckMechanism, ckKeyHandle); if (ckRv != CKR_OK) { - if (bTempKey) + if (ckKeyHandle != 0) (void) C_DestroyObject(ckSession, ckKeyHandle); kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; kmfh->lasterr.errcode = ckRv; @@ -553,7 +665,7 @@ PKCS_EncryptData(KMF_HANDLE_T kmfh, (CK_BYTE_PTR)out_data, &out_len); if (ckRv != CKR_OK) { - if (bTempKey) + if (ckKeyHandle != 0) (void) C_DestroyObject(ckSession, ckKeyHandle); kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; kmfh->lasterr.errcode = ckRv; @@ -568,7 +680,7 @@ PKCS_EncryptData(KMF_HANDLE_T kmfh, ciphertext->Length = total_encrypted; - if (bTempKey) + if (ckKeyHandle != 0) (void) C_DestroyObject(ckSession, ckKeyHandle); (void) C_CloseSession(ckSession); @@ -577,7 +689,7 @@ PKCS_EncryptData(KMF_HANDLE_T kmfh, } static void -DigestData(KMF_DATA *IDInput, KMF_DATA *IDOutput) +create_id_hash(KMF_DATA *IDInput, KMF_DATA *IDOutput) { SHA1_CTX ctx; @@ -616,9 +728,12 @@ GetIDFromSPKI(KMF_X509_SPKI *spki, KMF_DATA *ID) /* Check the KEY algorithm */ if (algId == KMF_ALGID_RSA) { - DigestData(&KeyParts[KMF_RSA_MODULUS], ID); + create_id_hash(&KeyParts[KMF_RSA_MODULUS], ID); } else if (algId == KMF_ALGID_DSA) { - DigestData(&KeyParts[KMF_DSA_PUBLIC_VALUE], ID); + create_id_hash(&KeyParts[KMF_DSA_PUBLIC_VALUE], ID); + } else if (algId == KMF_ALGID_SHA1WithECDSA || + algId == KMF_ALGID_ECDSA) { + create_id_hash(&KeyParts[KMF_ECDSA_POINT], ID); } else { /* We only support RSA and DSA keys for now */ rv = KMF_ERR_BAD_ALGORITHM; @@ -637,3 +752,112 @@ GetIDFromSPKI(KMF_X509_SPKI *spki, KMF_DATA *ID) return (rv); } + +/* + * For PKCS1 encoding (necessary for RSA signatures), we + * must prepend the following prefixes before computing + * the digest. + */ +static uchar_t SHA1_DER_PREFIX[] = { + 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, + 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 +}; +static uchar_t MD5_DER_PREFIX[] = { + 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, + 0x04, 0x10 +}; +static uchar_t SHA256_DER_PREFIX[] = {0x30, 0x31, 0x30, 0x0d, + 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, + 0x00, 0x04, 0x20}; + +static uchar_t SHA384_DER_PREFIX[] = {0x30, 0x41, 0x30, 0x0d, + 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, + 0x00, 0x04, 0x30}; + +static uchar_t SHA512_DER_PREFIX[] = {0x30, 0x51, 0x30, 0x0d, + 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, + 0x00, 0x04, 0x40}; + +#define MAX_SHA2_DIGEST_LENGTH 64 +/* + * Compute hashes using metaslot (or softtoken). + * Not all hardware tokens support the combined HASH + RSA/EC + * Signing operations so it is safer to separate the hashing + * from the signing. This function generates a hash using a + * separate session. The resulting digest can be signed later. + */ +KMF_RETURN +PKCS_DigestData(KMF_HANDLE_T handle, + CK_SESSION_HANDLE hSession, + CK_MECHANISM_TYPE mechtype, + KMF_DATA *tobesigned, KMF_DATA *output, + boolean_t pkcs1_encoding) +{ + KMF_RETURN rv = KMF_OK; + CK_RV ckrv; + CK_MECHANISM mechanism; + KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; + CK_BYTE outbuf[MAX_SHA2_DIGEST_LENGTH + + sizeof (SHA512_DER_PREFIX)]; + CK_ULONG outlen = sizeof (outbuf); + + mechanism.mechanism = mechtype; + mechanism.pParameter = NULL; + mechanism.ulParameterLen = 0; + + ckrv = C_DigestInit(hSession, &mechanism); + if (ckrv != CKR_OK) { + kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; + kmfh->lasterr.errcode = ckrv; + rv = KMF_ERR_INTERNAL; + goto end; + } + + ckrv = C_Digest(hSession, tobesigned->Data, + tobesigned->Length, outbuf, &outlen); + if (ckrv != CKR_OK) { + kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; + kmfh->lasterr.errcode = ckrv; + rv = KMF_ERR_INTERNAL; + } + + if (pkcs1_encoding) { + uchar_t *pfx; + int pfxlen; + switch (mechtype) { + case CKM_MD5: + pfx = MD5_DER_PREFIX; + pfxlen = sizeof (MD5_DER_PREFIX); + break; + case CKM_SHA_1: + pfx = SHA1_DER_PREFIX; + pfxlen = sizeof (SHA1_DER_PREFIX); + break; + case CKM_SHA256: + pfx = SHA256_DER_PREFIX; + pfxlen = sizeof (SHA256_DER_PREFIX); + break; + case CKM_SHA384: + pfx = SHA384_DER_PREFIX; + pfxlen = sizeof (SHA384_DER_PREFIX); + break; + case CKM_SHA512: + pfx = SHA512_DER_PREFIX; + pfxlen = sizeof (SHA512_DER_PREFIX); + break; + default: + rv = KMF_ERR_BAD_ALGORITHM; + goto end; + } + (void) memcpy(output->Data, pfx, pfxlen); + (void) memcpy(output->Data + pfxlen, outbuf, outlen); + output->Length = outlen + pfxlen; + } else { + (void) memcpy(output->Data, outbuf, outlen); + output->Length = outlen; + } + +end: + return (rv); +} diff --git a/usr/src/lib/libkmf/plugins/kmf_nss/common/nss_spi.c b/usr/src/lib/libkmf/plugins/kmf_nss/common/nss_spi.c index 5fe4f0a766..8a0e6ba862 100644 --- a/usr/src/lib/libkmf/plugins/kmf_nss/common/nss_spi.c +++ b/usr/src/lib/libkmf/plugins/kmf_nss/common/nss_spi.c @@ -22,7 +22,7 @@ /* * NSS keystore wrapper * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -154,7 +154,6 @@ KMF_PLUGIN_FUNCLIST nss_plugin_table = NSS_CreateSymKey, NSS_GetSymKeyValue, NSS_SetTokenPin, - NULL, /* VerifyData */ NSS_StoreKey, NULL /* Finalize */ }; @@ -683,7 +682,6 @@ NSS_FreeKMFCert(KMF_HANDLE_T handle, } } - KMF_RETURN NSS_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) { @@ -817,6 +815,7 @@ NSS_CreateKeypair(KMF_HANDLE_T handle, PK11SlotInfo *nss_slot = NULL; SECKEYPrivateKey *NSSprivkey = NULL; SECKEYPublicKey *NSSpubkey = NULL; + SECKEYECParams *ecparams = NULL; PQGParams *pqgParams = NULL; KMF_CREDENTIAL cred; boolean_t storekey = TRUE; @@ -936,6 +935,20 @@ NSS_CreateKeypair(KMF_HANDLE_T handle, } nssparams = pqgParams; + } else if (keytype == KMF_ECDSA) { + KMF_OID *eccoid = kmf_get_attr_ptr(KMF_ECC_CURVE_OID_ATTR, + attrlist, numattr); + if (eccoid == NULL) + return (KMF_ERR_BAD_PARAMETER); + + ecparams = SECITEM_AllocItem(NULL, NULL, (eccoid->Length)); + if (!ecparams) + return (KMF_ERR_MEMORY); + + (void) memcpy(ecparams->data, eccoid->Data, eccoid->Length); + + mechanism = CKM_EC_KEY_PAIR_GEN; + nssparams = ecparams; } else { rv = KMF_ERR_BAD_PARAMETER; goto cleanup; @@ -988,6 +1001,9 @@ cleanup: if (pqgParams != NULL) PK11_PQG_DestroyParams(pqgParams); + if (ecparams != NULL) + SECITEM_FreeItem(ecparams, PR_TRUE); + if (nss_slot != NULL) PK11_FreeSlot(nss_slot); @@ -1027,9 +1043,23 @@ NSS_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, signAlgTag = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION; else if (AlgId == KMF_ALGID_SHA1WithRSA) signAlgTag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; + else if (AlgId == KMF_ALGID_SHA256WithRSA) + signAlgTag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; + else if (AlgId == KMF_ALGID_SHA384WithRSA) + signAlgTag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; + else if (AlgId == KMF_ALGID_SHA512WithRSA) + signAlgTag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; else if (AlgId == KMF_ALGID_SHA1WithDSA) signAlgTag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST; - else + else if (AlgId == KMF_ALGID_SHA1WithECDSA || AlgId == KMF_ALGID_ECDSA) + signAlgTag = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST; + else if (AlgId == KMF_ALGID_SHA256WithECDSA) + signAlgTag = SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE; + else if (AlgId == KMF_ALGID_SHA384WithECDSA) + signAlgTag = SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE; + else if (AlgId == KMF_ALGID_SHA512WithECDSA) + signAlgTag = SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE; + else /* NSS does not support DSA with SHA2 hashes (FIPS 186-3) */ return (KMF_ERR_BAD_PARAMETER); rv = SEC_SignData(&signed_data, tobesigned->Data, @@ -1321,6 +1351,8 @@ pk11keytype2kmf(CK_KEY_TYPE type) return (KMF_DES); case CKK_DES3: return (KMF_DES3); + case CKK_EC: + return (KMF_ECDSA); default: /* not supported */ return (KMF_KEYALG_NONE); @@ -1437,6 +1469,8 @@ NSS_FindKey(KMF_HANDLE_T handle, keys[count].keyalg = KMF_RSA; else if (pubnode->key->keyType == dsaKey) keys[count].keyalg = KMF_DSA; + else if (pubnode->key->keyType == ecKey) + keys[count].keyalg = KMF_ECDSA; } if (match) count++; @@ -1469,6 +1503,8 @@ NSS_FindKey(KMF_HANDLE_T handle, keys[count].keyalg = KMF_RSA; else if (prinode->key->keyType == dsaKey) keys[count].keyalg = KMF_DSA; + else if (prinode->key->keyType == ecKey) + keys[count].keyalg = KMF_ECDSA; } if (match) count++; @@ -2188,12 +2224,16 @@ NSS_StoreKey(KMF_HANDLE_T handle, &rawkey->rawdata.rsa); if (rv != KMF_OK) goto cleanup; - } else if (rawkey->keytype == KMF_DSA) { rv = DerEncodeDSAPrivateKey(&derkey, &rawkey->rawdata.dsa); if (rv != KMF_OK) goto cleanup; + } else if (rawkey->keytype == KMF_ECDSA) { + rv = DerEncodeECPrivateKey(&derkey, + &rawkey->rawdata.ec); + if (rv != KMF_OK) + goto cleanup; } rpk.algorithm = nss_cert->subjectPublicKeyInfo.algorithm; rpk.privateKey.data = derkey.Data; diff --git a/usr/src/lib/libkmf/plugins/kmf_openssl/common/openssl_spi.c b/usr/src/lib/libkmf/plugins/kmf_openssl/common/openssl_spi.c index 59def17c80..f7ffa36662 100644 --- a/usr/src/lib/libkmf/plugins/kmf_openssl/common/openssl_spi.c +++ b/usr/src/lib/libkmf/plugins/kmf_openssl/common/openssl_spi.c @@ -259,10 +259,6 @@ OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *); KMF_RETURN OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *); -KMF_RETURN -OpenSSL_VerifyDataWithCert(KMF_HANDLE_T, KMF_ALGORITHM_INDEX, - KMF_DATA *, KMF_DATA *, KMF_DATA *); - static KMF_PLUGIN_FUNCLIST openssl_plugin_table = { @@ -290,7 +286,6 @@ KMF_PLUGIN_FUNCLIST openssl_plugin_table = OpenSSL_CreateSymKey, OpenSSL_GetSymKeyValue, NULL, /* SetTokenPin */ - OpenSSL_VerifyDataWithCert, OpenSSL_StoreKey, NULL /* Finalize */ }; @@ -678,7 +673,6 @@ load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial, rv = KMF_ERR_CERT_NOT_FOUND; return (rv); } - if (format == KMF_FORMAT_ASN1) { /* load a single certificate */ certs = (KMF_DATA *)malloc(sizeof (KMF_DATA)); @@ -697,13 +691,12 @@ load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial, certs = NULL; } return (rv); - } else if (format == KMF_FORMAT_PKCS12) { /* We need a credential to access a PKCS#12 file */ rv = KMF_ERR_BAD_CERT_FORMAT; - } else if (format == KMF_FORMAT_PEM || format != KMF_FORMAT_PEM_KEYPAIR) { + /* This function only works on PEM files */ rv = extract_pem(kmfh, issuer, subject, serial, pathname, (uchar_t *)NULL, 0, NULL, &certs, &nc); @@ -724,7 +717,6 @@ load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial, if (rv == KMF_ERR_VALIDITY_PERIOD) rv = KMF_OK; } - if (rv != KMF_OK) { /* Remove this cert from the list by clearing it. */ kmf_free_data(&certs[i]); @@ -733,7 +725,6 @@ load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial, } rv = KMF_OK; } - if (rv == KMF_OK && hits > 0) { /* * Sort the list of certs by length to put the cleared ones @@ -744,23 +735,17 @@ load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial, /* since we sorted the list, just return the number of hits */ *numcerts = hits; - } else { - if (rv == KMF_OK && hits == 0) { + if (rv == KMF_OK && hits == 0) rv = KMF_ERR_CERT_NOT_FOUND; - } - if (certs != NULL) { - kmf_free_data(certs); free(certs); certs = NULL; } } - return (rv); } - static KMF_RETURN kmf_load_cert(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial, @@ -1211,9 +1196,7 @@ OpenSSL_FreeKMFCert(KMF_HANDLE_T handle, { if (kmf_cert != NULL) { if (kmf_cert->certificate.Data != NULL) { - free(kmf_cert->certificate.Data); - kmf_cert->certificate.Data = NULL; - kmf_cert->certificate.Length = 0; + kmf_free_data(&kmf_cert->certificate); } if (kmf_cert->kmf_private.label) free(kmf_cert->kmf_private.label); @@ -1333,8 +1316,7 @@ OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) if (rv == KMF_ERR_CERT_NOT_FOUND) { free(fname); - if (certdata.Data) - free(certdata.Data); + kmf_free_data(&certdata); rv = KMF_OK; continue; } else if (rv != KMF_OK) { @@ -1349,8 +1331,7 @@ OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) break; } free(fname); - if (certdata.Data) - free(certdata.Data); + kmf_free_data(&certdata); } } (void) closedir(dirp); @@ -1370,8 +1351,7 @@ out: if (fullpath != NULL) free(fullpath); - if (certdata.Data) - free(certdata.Data); + kmf_free_data(&certdata); return (rv); } @@ -1767,6 +1747,21 @@ cleanup: return (rv); } +/* + * Make sure the BN conversion is properly padded with 0x00 + * bytes. If not, signature verification for DSA signatures + * may fail in the case where the bignum value does not use + * all of the bits. + */ +static int +fixbnlen(BIGNUM *bn, unsigned char *buf, int len) { + int bytes = len - BN_num_bytes(bn); + while (bytes-- > 0) + *buf++ = 0; + + return (BN_bn2bin(bn, buf)); +} + KMF_RETURN OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output) @@ -1786,7 +1781,7 @@ OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, /* Map the OID to an OpenSSL algorithm */ AlgId = x509_algoid_to_algid(AlgOID); if (AlgId == KMF_ALGID_NONE) - return (KMF_ERR_BAD_PARAMETER); + return (KMF_ERR_BAD_ALGORITHM); if (key->keyalg == KMF_RSA) { EVP_PKEY *pkey = (EVP_PKEY *)key->keyp; @@ -1798,10 +1793,16 @@ OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, md = EVP_md2(); else if (AlgId == KMF_ALGID_SHA1WithRSA) md = EVP_sha1(); + else if (AlgId == KMF_ALGID_SHA256WithRSA) + md = EVP_sha256(); + else if (AlgId == KMF_ALGID_SHA384WithRSA) + md = EVP_sha384(); + else if (AlgId == KMF_ALGID_SHA512WithRSA) + md = EVP_sha512(); else if (AlgId == KMF_ALGID_RSA) md = NULL; else - return (KMF_ERR_BAD_PARAMETER); + return (KMF_ERR_BAD_ALGORITHM); if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) { RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey); @@ -1836,6 +1837,14 @@ OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, uint32_t hashlen; DSA_SIG *dsasig; + if (AlgId == KMF_ALGID_DSA || + AlgId == KMF_ALGID_SHA1WithDSA) + md = EVP_sha1(); + else if (AlgId == KMF_ALGID_SHA256WithDSA) + md = EVP_sha256(); + else /* Bad algorithm */ + return (KMF_ERR_BAD_ALGORITHM); + /* * OpenSSL EVP_Sign operation automatically converts to * ASN.1 output so we do the operations separately so we @@ -1844,24 +1853,27 @@ OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, * not all mechanisms return ASN.1 encodings (PKCS#11 * and NSS return raw signature data). */ - md = EVP_sha1(); EVP_MD_CTX_init(&ctx); (void) EVP_DigestInit_ex(&ctx, md, NULL); (void) EVP_DigestUpdate(&ctx, tobesigned->Data, tobesigned->Length); (void) EVP_DigestFinal_ex(&ctx, hash, &hashlen); - (void) EVP_MD_CTX_cleanup(&ctx); + /* Only sign first 20 bytes for SHA2 */ + if (AlgId == KMF_ALGID_SHA256WithDSA) + hashlen = 20; dsasig = DSA_do_sign(hash, hashlen, dsa); if (dsasig != NULL) { int i; - output->Length = i = BN_bn2bin(dsasig->r, output->Data); - output->Length += BN_bn2bin(dsasig->s, - &output->Data[i]); + output->Length = i = fixbnlen(dsasig->r, output->Data, + hashlen); + output->Length += fixbnlen(dsasig->s, &output->Data[i], + hashlen); DSA_SIG_free(dsasig); } else { SET_ERROR(kmfh, ERR_get_error()); } + (void) EVP_MD_CTX_cleanup(&ctx); } else { return (KMF_ERR_BAD_PARAMETER); } @@ -2429,7 +2441,7 @@ OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle, end: /* - * We don't need to free "id" explicitly, because OCSP_REQUEST_free() + * We don't need to free "id" explicitely, because OCSP_REQUEST_free() * will also deallocate certid's space. */ if (req != NULL) { @@ -3203,6 +3215,12 @@ raw_key_to_pkey(KMF_KEY_HANDLE *key) pkey = ImportRawRSAKey(&rawkey->rawdata.rsa); } else if (rawkey->keytype == KMF_DSA) { pkey = ImportRawDSAKey(&rawkey->rawdata.dsa); + } else if (rawkey->keytype == KMF_ECDSA) { + /* + * OpenSSL in Solaris does not support EC for + * legal reasons + */ + return (NULL); } else { /* wrong kind of key */ return (NULL); @@ -3649,7 +3667,9 @@ extract_pem(KMF_HANDLE *kmfh, &certlist[matchcerts++]); if (rv != KMF_OK) { - kmf_free_data(certlist); + int j; + for (j = 0; j < matchcerts; j++) + kmf_free_data(&certlist[j]); free(certlist); certlist = NULL; ncerts = matchcerts = 0; @@ -3659,10 +3679,11 @@ extract_pem(KMF_HANDLE *kmfh, if (numcerts != NULL) *numcerts = matchcerts; - if (certs != NULL) { + if (certs != NULL) *certs = certlist; - } else if (certlist != NULL) { - kmf_free_data(certlist); + else if (certlist != NULL) { + for (i = 0; i < ncerts; i++) + kmf_free_data(&certlist[i]); free(certlist); certlist = NULL; } @@ -3688,7 +3709,6 @@ err: return (rv); } - static KMF_RETURN openssl_parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, char *pin, STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs) @@ -3728,7 +3748,7 @@ set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid) X509_ATTRIBUTE *a; for (i = 0; i < sk_X509_ATTRIBUTE_num(pkey->attributes); i++) { - /* LINTED E_BAD_PTR_CAST_ALIGN */ + /* LINTED E_BAD_PTR_CASE_ALIGN */ a = sk_X509_ATTRIBUTE_value(pkey->attributes, i); if (OBJ_obj2nid(a->object) == nid) { X509_ATTRIBUTE_free(a); @@ -4385,14 +4405,12 @@ openssl_import_objects(KMF_HANDLE *kmfh, (void) sk_EVP_PKEY_push(privkeys, pkey); /* convert the certificate list here */ if (*ncerts > 0 && certlist != NULL) { - kmfcerts = (KMF_X509_DER_CERT *)malloc(*ncerts * + kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts, sizeof (KMF_X509_DER_CERT)); if (kmfcerts == NULL) { rv = KMF_ERR_MEMORY; goto end; } - (void) memset(kmfcerts, 0, *ncerts * - sizeof (KMF_X509_DER_CERT)); for (i = 0; i < *ncerts; i++) { kmfcerts[i].certificate = certdata[i]; kmfcerts[i].kmf_private.keystore_type = @@ -4781,208 +4799,6 @@ OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey, } /* - * id-sha1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) oiw(14) secsig(3) - * algorithms(2) 26 - * } - */ -#define ASN1_SHA1_OID_PREFIX_LEN 15 -static uchar_t SHA1_DER_PREFIX[ASN1_SHA1_OID_PREFIX_LEN] = { - 0x30, 0x21, 0x30, 0x09, - 0x06, 0x05, 0x2b, 0x0e, - 0x03, 0x02, 0x1a, 0x05, - 0x00, 0x04, 0x14 -}; - -/* - * id-md2 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2 - * } - */ -#define ASN1_MD2_OID_PREFIX_LEN 18 -static uchar_t MD2_DER_PREFIX[ASN1_MD2_OID_PREFIX_LEN] = { - 0x30, 0x20, 0x30, 0x0c, - 0x06, 0x08, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, - 0x02, 0x02, 0x05, 0x00, - 0x04, 0x10 -}; - -/* - * id-md5 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 - * } - */ -#define ASN1_MD5_OID_PREFIX_LEN 18 -static uchar_t MD5_DER_PREFIX[ASN1_MD5_OID_PREFIX_LEN] = { - 0x30, 0x20, 0x30, 0x0c, - 0x06, 0x08, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, - 0x02, 0x05, 0x05, 0x00, - 0x04, 0x10 -}; - -KMF_RETURN -OpenSSL_VerifyDataWithCert(KMF_HANDLE_T handle, - KMF_ALGORITHM_INDEX algid, KMF_DATA *indata, - KMF_DATA *insig, KMF_DATA *cert) -{ - KMF_RETURN ret = KMF_OK; - KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; - X509 *xcert = NULL; - EVP_PKEY *pkey = NULL; - uchar_t *p; - uchar_t *rsaout = NULL; - uchar_t *pfx = NULL; - const EVP_MD *md; - int pfxlen = 0, len; - - if (handle == NULL || indata == NULL || - indata->Data == NULL || indata->Length == 0 || - insig == NULL|| insig->Data == NULL || insig->Length == 0 || - cert == NULL || cert->Data == NULL || cert->Length == 0) - return (KMF_ERR_BAD_PARAMETER); - - p = cert->Data; - xcert = d2i_X509(NULL, (const uchar_t **)&p, cert->Length); - if (xcert == NULL) { - SET_ERROR(kmfh, ERR_get_error()); - ret = KMF_ERR_BAD_CERT_FORMAT; - goto cleanup; - } - - pkey = X509_get_pubkey(xcert); - if (pkey == NULL) { - SET_ERROR(kmfh, ERR_get_error()); - ret = KMF_ERR_BAD_CERT_FORMAT; - goto cleanup; - } - - if (algid != KMF_ALGID_NONE) { - switch (algid) { - case KMF_ALGID_MD5WithRSA: - md = EVP_md5(); - break; - case KMF_ALGID_MD2WithRSA: - md = EVP_md2(); - break; - case KMF_ALGID_SHA1WithRSA: - md = EVP_sha1(); - break; - case KMF_ALGID_RSA: - md = NULL; - break; - default: - ret = KMF_ERR_BAD_PARAMETER; - goto cleanup; - } - } else { - /* Get the hash type from the cert signature */ - md = EVP_get_digestbyobj(xcert->sig_alg->algorithm); - if (md == NULL) { - SET_ERROR(kmfh, ERR_get_error()); - ret = KMF_ERR_BAD_PARAMETER; - goto cleanup; - } - } - if (md != NULL) { - switch (EVP_MD_type(md)) { - case NID_md2: - case NID_md2WithRSAEncryption: - pfxlen = ASN1_MD2_OID_PREFIX_LEN; - pfx = MD2_DER_PREFIX; - break; - case NID_md5: - case NID_md5WithRSAEncryption: - pfxlen = ASN1_MD5_OID_PREFIX_LEN; - pfx = MD5_DER_PREFIX; - break; - case NID_sha1: - case NID_sha1WithRSAEncryption: - pfxlen = ASN1_SHA1_OID_PREFIX_LEN; - pfx = SHA1_DER_PREFIX; - break; - default: /* Unsupported */ - pfxlen = 0; - pfx = NULL; - break; - } - } - - /* RSA with no hash is a special case */ - rsaout = malloc(RSA_size(pkey->pkey.rsa)); - if (rsaout == NULL) - return (KMF_ERR_MEMORY); - - /* Decrypt the input signature */ - len = RSA_public_decrypt(insig->Length, - insig->Data, rsaout, pkey->pkey.rsa, RSA_PKCS1_PADDING); - if (len < 1) { - SET_ERROR(kmfh, ERR_get_error()); - ret = KMF_ERR_BAD_PARAMETER; - } else { - size_t hashlen = 0; - uint32_t dlen; - char *digest = NULL; - - /* - * If the AlgId requires it, hash the input data before - * comparing it to the decrypted signature. - */ - if (md) { - EVP_MD_CTX ctx; - - hashlen = md->md_size; - - digest = malloc(hashlen + pfxlen); - if (digest == NULL) - return (KMF_ERR_MEMORY); - /* Add the prefix to the comparison buffer. */ - if (pfx && pfxlen > 0) { - (void) memcpy(digest, pfx, pfxlen); - } - (void) EVP_DigestInit(&ctx, md); - (void) EVP_DigestUpdate(&ctx, indata->Data, - indata->Length); - - /* Add the digest AFTER the ASN1 prefix */ - (void) EVP_DigestFinal(&ctx, - (uchar_t *)digest + pfxlen, &dlen); - - dlen += pfxlen; - } else { - digest = (char *)indata->Data; - dlen = indata->Length; - } - - /* - * The result of the RSA decryption should be ASN1(OID | Hash). - * Compare the output hash to the input data for the final - * result. - */ - if (memcmp(rsaout, digest, dlen)) - ret = KMF_ERR_INTERNAL; - else - ret = KMF_OK; - - /* If we had to allocate space for the digest, free it now */ - if (hashlen) - free(digest); - } -cleanup: - if (pkey) - EVP_PKEY_free(pkey); - - if (xcert) - X509_free(xcert); - - if (rsaout) - free(rsaout); - - return (ret); -} - -/* * substitute for the unsafe access(2) function. * If the file in question already exists, return 1. * else 0. If an error occurs during testing (other diff --git a/usr/src/lib/libkmf/plugins/kmf_pkcs11/common/pkcs11_spi.c b/usr/src/lib/libkmf/plugins/kmf_pkcs11/common/pkcs11_spi.c index 8d65701ebd..104612f1e9 100644 --- a/usr/src/lib/libkmf/plugins/kmf_pkcs11/common/pkcs11_spi.c +++ b/usr/src/lib/libkmf/plugins/kmf_pkcs11/common/pkcs11_spi.c @@ -21,7 +21,7 @@ /* * PKCS11 token KMF Plugin * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -31,7 +31,6 @@ #include <kmfapiP.h> #include <ber_der.h> -#include <algorithm.h> #include <fcntl.h> #include <sha1.h> #include <bignum.h> @@ -127,10 +126,6 @@ KMF_RETURN KMFPK11_SetTokenPin(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); KMF_RETURN -KMFPK11_VerifyDataWithCert(KMF_HANDLE_T, KMF_ALGORITHM_INDEX, KMF_DATA *, - KMF_DATA *, KMF_DATA *); - -KMF_RETURN KMFPK11_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); @@ -161,7 +156,6 @@ KMF_PLUGIN_FUNCLIST pk11token_plugin_table = KMFPK11_CreateSymKey, KMFPK11_GetSymKeyValue, KMFPK11_SetTokenPin, - KMFPK11_VerifyDataWithCert, KMFPK11_StoreKey, NULL /* Finalize */ }; @@ -777,7 +771,7 @@ KMFPK11_FreeKMFCert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert) KMF_RETURN KMFPK11_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *pKey, - KMF_DATA *eData) + KMF_DATA *eData) { KMF_RETURN ret = KMF_OK; CK_RV rv; @@ -789,9 +783,11 @@ KMFPK11_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *pKey, BerElement *asn1 = NULL; BerValue *PubKeyParams = NULL, *EncodedKey = NULL; KMF_X509_SPKI spki; + CK_BYTE ec_params[256], ec_point[256]; CK_ATTRIBUTE rsaTemplate[4]; CK_ATTRIBUTE dsaTemplate[6]; + CK_ATTRIBUTE ecdsaTemplate[6]; if (kmfh == NULL) return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */ @@ -809,21 +805,16 @@ KMFPK11_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *pKey, (void) memset(&Base, 0, sizeof (Base)); (void) memset(&Value, 0, sizeof (Value)); - SETATTR(rsaTemplate, 0, CKA_CLASS, &ckObjClass, sizeof (ckObjClass)); - SETATTR(rsaTemplate, 1, CKA_KEY_TYPE, &ckKeyType, sizeof (ckKeyType)); - SETATTR(rsaTemplate, 2, CKA_MODULUS, Modulus.Data, Modulus.Length); - SETATTR(rsaTemplate, 3, CKA_PUBLIC_EXPONENT, Exponent.Data, - Exponent.Length); - - SETATTR(dsaTemplate, 0, CKA_CLASS, &ckObjClass, sizeof (ckObjClass)); - SETATTR(dsaTemplate, 1, CKA_KEY_TYPE, &ckKeyType, sizeof (ckKeyType)); - SETATTR(dsaTemplate, 2, CKA_PRIME, Prime.Data, Prime.Length); - SETATTR(dsaTemplate, 3, CKA_SUBPRIME, Subprime.Data, Subprime.Length); - SETATTR(dsaTemplate, 4, CKA_BASE, Base.Data, Base.Length); - SETATTR(dsaTemplate, 5, CKA_VALUE, Value.Data, Value.Length); - switch (pKey->keyalg) { case KMF_RSA: + SETATTR(rsaTemplate, 0, CKA_CLASS, &ckObjClass, + sizeof (ckObjClass)); + SETATTR(rsaTemplate, 1, CKA_KEY_TYPE, &ckKeyType, + sizeof (ckKeyType)); + SETATTR(rsaTemplate, 2, CKA_MODULUS, Modulus.Data, + Modulus.Length); + SETATTR(rsaTemplate, 3, CKA_PUBLIC_EXPONENT, + Exponent.Data, Exponent.Length); /* Get the length of the fields */ rv = C_GetAttributeValue(kmfh->pk11handle, (CK_OBJECT_HANDLE)pKey->keyp, rsaTemplate, 4); @@ -893,6 +884,19 @@ KMFPK11_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *pKey, break; case KMF_DSA: + SETATTR(dsaTemplate, 0, CKA_CLASS, &ckObjClass, + sizeof (ckObjClass)); + SETATTR(dsaTemplate, 1, CKA_KEY_TYPE, &ckKeyType, + sizeof (ckKeyType)); + SETATTR(dsaTemplate, 2, CKA_PRIME, Prime.Data, + Prime.Length); + SETATTR(dsaTemplate, 3, CKA_SUBPRIME, Subprime.Data, + Subprime.Length); + SETATTR(dsaTemplate, 4, CKA_BASE, Base.Data, + Base.Length); + SETATTR(dsaTemplate, 5, CKA_VALUE, Value.Data, + Value.Length); + /* Get the length of the fields */ rv = C_GetAttributeValue(kmfh->pk11handle, (CK_OBJECT_HANDLE)pKey->keyp, dsaTemplate, 6); @@ -1008,6 +1012,41 @@ KMFPK11_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *pKey, kmfber_free(asn1, 1); free(Value.Data); break; + case KMF_ECDSA: + /* The EC_PARAMS are the PubKey algorithm parameters */ + PubKeyParams = calloc(1, sizeof (BerValue)); + if (PubKeyParams == NULL) + return (KMF_ERR_MEMORY); + EncodedKey = calloc(1, sizeof (BerValue)); + if (EncodedKey == NULL) { + free(PubKeyParams); + return (KMF_ERR_MEMORY); + } + SETATTR(ecdsaTemplate, 0, CKA_EC_PARAMS, + &ec_params, sizeof (ec_params)); + SETATTR(ecdsaTemplate, 1, CKA_EC_POINT, + &ec_point, sizeof (ec_point)); + + /* Get the length of the fields */ + rv = C_GetAttributeValue(kmfh->pk11handle, + (CK_OBJECT_HANDLE)pKey->keyp, + ecdsaTemplate, 2); + if (rv != CKR_OK) { + SET_ERROR(kmfh, rv); + return (KMF_ERR_BAD_PARAMETER); + } + /* The params are to be used as algorithm parameters */ + PubKeyParams->bv_val = (char *)ec_params; + PubKeyParams->bv_len = ecdsaTemplate[0].ulValueLen; + /* + * The EC_POINT is to be used as the subject pub key. + */ + EncodedKey->bv_val = (char *)ec_point; + EncodedKey->bv_len = ecdsaTemplate[1].ulValueLen; + + /* Use the EC_PUBLIC_KEY OID */ + Algorithm = (KMF_OID *)&KMFOID_EC_PUBLIC_KEY; + break; default: return (KMF_ERR_BAD_PARAMETER); } @@ -1036,12 +1075,14 @@ KMFPK11_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *pKey, cleanup: if (EncodedKey) { - free(EncodedKey->bv_val); + if (pKey->keyalg != KMF_ECDSA) + free(EncodedKey->bv_val); free(EncodedKey); } if (PubKeyParams) { - free(PubKeyParams->bv_val); + if (pKey->keyalg != KMF_ECDSA) + free(PubKeyParams->bv_val); free(PubKeyParams); } @@ -1363,32 +1404,18 @@ out: return (rv); } -KMF_RETURN -KMFPK11_CreateKeypair(KMF_HANDLE_T handle, - int numattr, - KMF_ATTRIBUTE *attlist) +static CK_RV +gendsa_keypair(KMF_HANDLE *kmfh, boolean_t storekey, + CK_OBJECT_HANDLE *pubKey, + CK_OBJECT_HANDLE *priKey) { - KMF_RETURN rv = KMF_OK; - KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; - - CK_RV ckrv = 0; - CK_OBJECT_HANDLE pubKey = CK_INVALID_HANDLE; - CK_OBJECT_HANDLE priKey = CK_INVALID_HANDLE; - CK_SESSION_HANDLE hSession = kmfh->pk11handle; - - static CK_OBJECT_CLASS priClass = CKO_PRIVATE_KEY; - static CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY; - - static CK_ULONG modulusBits = 1024; - uint32_t modulusBits_size = sizeof (CK_ULONG); - static CK_BYTE PubExpo[3] = {0x01, 0x00, 0x01}; + CK_RV ckrv = CKR_OK; + CK_SESSION_HANDLE hSession = kmfh->pk11handle; + static CK_ULONG dsaKeyType = CKK_DSA; static CK_BBOOL true = TRUE; - static CK_BBOOL ontoken = TRUE; static CK_BBOOL false = FALSE; - static CK_ULONG dsaKeyType = CKK_DSA; - - CK_ATTRIBUTE rsaPubKeyTemplate[16]; - CK_ATTRIBUTE rsaPriKeyTemplate[16]; + static CK_OBJECT_CLASS priClass = CKO_PRIVATE_KEY; + static CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY; static CK_BYTE ckDsaPrime[128] = { 0xb2, 0x6b, 0xc3, 0xfb, 0xe3, 0x26, 0xf4, 0xc2, @@ -1434,7 +1461,7 @@ KMFPK11_CreateKeypair(KMF_HANDLE_T handle, static CK_ATTRIBUTE ckDsaPubKeyTemplate[] = { { CKA_CLASS, &pubClass, sizeof (pubClass) }, { CKA_KEY_TYPE, &dsaKeyType, sizeof (dsaKeyType) }, - { CKA_TOKEN, &ontoken, sizeof (ontoken)}, + { CKA_TOKEN, &true, sizeof (true)}, { CKA_PRIVATE, &false, sizeof (false)}, { CKA_PRIME, &ckDsaPrime, sizeof (ckDsaPrime) }, { CKA_SUBPRIME, &ckDsaSubPrime, sizeof (ckDsaSubPrime)}, @@ -1450,26 +1477,201 @@ KMFPK11_CreateKeypair(KMF_HANDLE_T handle, static CK_ATTRIBUTE ckDsaPriKeyTemplate[] = { {CKA_CLASS, &priClass, sizeof (priClass)}, {CKA_KEY_TYPE, &dsaKeyType, sizeof (dsaKeyType)}, - {CKA_TOKEN, &ontoken, sizeof (ontoken)}, + {CKA_TOKEN, &true, sizeof (true)}, {CKA_PRIVATE, &true, sizeof (true)}, {CKA_SIGN, &true, sizeof (true)}, }; +#define NUMBER_DSA_PRI_TEMPLATES (sizeof (ckDsaPriKeyTemplate) / \ + sizeof (CK_ATTRIBUTE)) +#define MAX_DSA_PRI_TEMPLATES (sizeof (ckDsaPriKeyTemplate) / \ + sizeof (CK_ATTRIBUTE)) + CK_MECHANISM keyGenMech = {CKM_DSA_KEY_PAIR_GEN, NULL, 0}; + + SETATTR(ckDsaPriKeyTemplate, 2, CKA_TOKEN, + (storekey ? &true : &false), sizeof (CK_BBOOL)); + + ckrv = C_GenerateKeyPair(hSession, &keyGenMech, + ckDsaPubKeyTemplate, + (sizeof (ckDsaPubKeyTemplate)/sizeof (CK_ATTRIBUTE)), + ckDsaPriKeyTemplate, + (sizeof (ckDsaPriKeyTemplate)/sizeof (CK_ATTRIBUTE)), + pubKey, priKey); + if (ckrv != CKR_OK) { + SET_ERROR(kmfh, ckrv); + return (KMF_ERR_KEYGEN_FAILED); + } + + return (ckrv); +} + +static CK_RV +genrsa_keypair(KMF_HANDLE *kmfh, CK_ULONG modulusBits, + boolean_t storekey, KMF_BIGINT *rsaexp, + CK_OBJECT_HANDLE *pubKey, + CK_OBJECT_HANDLE *priKey) +{ + CK_RV ckrv = CKR_OK; + CK_SESSION_HANDLE hSession = kmfh->pk11handle; + CK_ATTRIBUTE rsaPubKeyTemplate[16]; + CK_ATTRIBUTE rsaPriKeyTemplate[16]; + CK_MECHANISM keyGenMech = {CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0}; + int numpubattr = 0, numpriattr = 0; + static CK_BYTE PubExpo[3] = {0x01, 0x00, 0x01}; + static CK_BBOOL true = TRUE; + static CK_BBOOL false = FALSE; + + SETATTR(rsaPubKeyTemplate, numpubattr, CKA_TOKEN, + (storekey ? &true : &false), sizeof (CK_BBOOL)); + numpubattr++; + + SETATTR(rsaPubKeyTemplate, numpubattr, CKA_MODULUS_BITS, + &modulusBits, sizeof (modulusBits)); + numpubattr++; + + if (rsaexp != NULL && (rsaexp->len > 0 && rsaexp->val != NULL)) { + SETATTR(rsaPubKeyTemplate, numpubattr, + CKA_PUBLIC_EXPONENT, + rsaexp->val, rsaexp->len); + numpubattr++; + } else { + SETATTR(rsaPubKeyTemplate, numpubattr, + CKA_PUBLIC_EXPONENT, &PubExpo, sizeof (PubExpo)); + numpubattr++; + } + SETATTR(rsaPubKeyTemplate, numpubattr, CKA_ENCRYPT, + &true, sizeof (true)); + numpubattr++; + SETATTR(rsaPubKeyTemplate, numpubattr, CKA_VERIFY, + &true, sizeof (true)); + numpubattr++; + SETATTR(rsaPubKeyTemplate, numpubattr, CKA_WRAP, + &true, sizeof (true)); + numpubattr++; + + SETATTR(rsaPriKeyTemplate, numpriattr, CKA_TOKEN, + (storekey ? &true : &false), sizeof (CK_BBOOL)); + numpriattr++; + SETATTR(rsaPriKeyTemplate, numpriattr, CKA_PRIVATE, &true, + sizeof (true)); + numpriattr++; + SETATTR(rsaPriKeyTemplate, numpriattr, CKA_DECRYPT, &true, + sizeof (true)); + numpriattr++; + SETATTR(rsaPriKeyTemplate, numpriattr, CKA_SIGN, &true, + sizeof (true)); + numpriattr++; + SETATTR(rsaPriKeyTemplate, numpriattr, CKA_UNWRAP, &true, + sizeof (true)); + numpriattr++; + + ckrv = C_GenerateKeyPair(hSession, &keyGenMech, + rsaPubKeyTemplate, numpubattr, + rsaPriKeyTemplate, numpriattr, + pubKey, priKey); + if (ckrv != CKR_OK) { + SET_ERROR(kmfh, ckrv); + return (ckrv); + } + + return (ckrv); +} + +static CK_RV +genecc_keypair(KMF_HANDLE *kmfh, + boolean_t ontoken, + KMF_OID *curveoid, + CK_OBJECT_HANDLE *pubKey, + CK_OBJECT_HANDLE *priKey) +{ + CK_RV ckrv; + CK_SESSION_HANDLE hSession = kmfh->pk11handle; + CK_MECHANISM keyGenMech = {CKM_EC_KEY_PAIR_GEN, NULL, 0}; + const ulong_t publicKey = CKO_PUBLIC_KEY; + const ulong_t privateKey = CKO_PRIVATE_KEY; + const ulong_t keytype = CKK_EC; + static CK_BBOOL true = TRUE; + static CK_BBOOL false = FALSE; + CK_ATTRIBUTE public_template[6]; + CK_ATTRIBUTE private_template[6]; + int numpubattr, numpriattr; + + numpubattr = 0; + SETATTR(public_template, numpubattr, CKA_CLASS, + &publicKey, sizeof (publicKey)); + numpubattr++; + SETATTR(public_template, numpubattr, CKA_KEY_TYPE, + &keytype, sizeof (keytype)); + numpubattr++; + SETATTR(public_template, numpubattr, CKA_EC_PARAMS, + curveoid->Data, curveoid->Length); + numpubattr++; + SETATTR(public_template, numpubattr, CKA_TOKEN, + ontoken ? &true : &false, sizeof (true)); + numpubattr++; + SETATTR(public_template, numpubattr, CKA_VERIFY, + &true, sizeof (true)); + numpubattr++; + SETATTR(public_template, numpubattr, CKA_PRIVATE, + &false, sizeof (false)); + numpubattr++; + + numpriattr = 0; + SETATTR(private_template, numpriattr, CKA_CLASS, + &privateKey, sizeof (privateKey)); + numpriattr++; + SETATTR(private_template, numpriattr, CKA_KEY_TYPE, + &keytype, sizeof (keytype)); + numpriattr++; + SETATTR(private_template, numpriattr, CKA_TOKEN, + ontoken ? &true : &false, sizeof (true)); + numpriattr++; + SETATTR(private_template, numpriattr, CKA_PRIVATE, + &true, sizeof (true)); + numpriattr++; + SETATTR(private_template, numpriattr, CKA_SIGN, + &true, sizeof (true)); + numpriattr++; + SETATTR(private_template, numpriattr, CKA_DERIVE, + &true, sizeof (true)); + numpriattr++; + + ckrv = C_GenerateKeyPair(hSession, &keyGenMech, + public_template, numpubattr, + private_template, numpriattr, + pubKey, priKey); + if (ckrv != CKR_OK) { + SET_ERROR(kmfh, ckrv); + return (ckrv); + } + + return (ckrv); +} + +KMF_RETURN +KMFPK11_CreateKeypair(KMF_HANDLE_T handle, + int numattr, + KMF_ATTRIBUTE *attlist) +{ + KMF_RETURN rv = KMF_OK; + KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; + KMF_DATA IDInput, IDOutput; + KMF_CREDENTIAL *cred; + KMF_KEY_ALG keytype = KMF_RSA; + KMF_KEY_HANDLE *pubkey, *privkey; + + CK_RV ckrv = 0; + CK_SESSION_HANDLE hSession = kmfh->pk11handle; CK_ATTRIBUTE labelattr[1]; CK_ATTRIBUTE idattr[1]; + CK_OBJECT_HANDLE pubKey, priKey; + char IDHashData[SHA1_HASH_LENGTH]; - KMF_DATA IDInput, IDOutput; + static CK_ULONG modulusBits = 1024; + uint32_t modulusBits_size = sizeof (CK_ULONG); SHA1_CTX ctx; - KMF_CREDENTIAL *cred; - KMF_KEY_ALG keytype = KMF_RSA; boolean_t storekey = TRUE; char *keylabel = NULL; - KMF_KEY_HANDLE *pubkey, *privkey; - -#define NUMBER_DSA_PRI_TEMPLATES (sizeof (ckDsaPriKeyTemplate) / \ - sizeof (CK_ATTRIBUTE)) -#define MAX_DSA_PRI_TEMPLATES (sizeof (ckDsaPriKeyTemplate) / \ - sizeof (CK_ATTRIBUTE)) if (kmfh == NULL) return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */ @@ -1504,12 +1706,10 @@ KMFPK11_CreateKeypair(KMF_HANDLE_T handle, (void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE)); (void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE)); if (keytype == KMF_RSA) { - CK_MECHANISM keyGenMech = {CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0}; - CK_BYTE *modulus; + CK_BYTE *modulus = NULL; CK_ULONG modulusLength = 0; - CK_ATTRIBUTE modattr[1]; KMF_BIGINT *rsaexp = NULL; - int numpubattr = 0, numpriattr = 0; + CK_ATTRIBUTE modattr[1]; rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attlist, numattr, &modulusBits, &modulusBits_size); @@ -1519,64 +1719,14 @@ KMFPK11_CreateKeypair(KMF_HANDLE_T handle, if (rv != KMF_OK) return (KMF_ERR_BAD_PARAMETER); - SETATTR(rsaPubKeyTemplate, numpubattr, CKA_TOKEN, - (storekey ? &true : &false), sizeof (CK_BBOOL)); - numpubattr++; + rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attlist, numattr); - SETATTR(rsaPubKeyTemplate, numpubattr, CKA_MODULUS_BITS, - &modulusBits, sizeof (modulusBits)); - numpubattr++; + /* Generate the RSA keypair */ + ckrv = genrsa_keypair(kmfh, modulusBits, storekey, + rsaexp, &pubKey, &priKey); - if ((rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attlist, - numattr)) != NULL && - (rsaexp->len > 0 && rsaexp->val != NULL)) { - SETATTR(rsaPubKeyTemplate, numpubattr, - CKA_PUBLIC_EXPONENT, - rsaexp->val, rsaexp->len); - numpubattr++; - } else { - rv = KMF_OK; - SETATTR(rsaPubKeyTemplate, numpubattr, - CKA_PUBLIC_EXPONENT, &PubExpo, sizeof (PubExpo)); - numpubattr++; - } - SETATTR(rsaPubKeyTemplate, numpubattr, CKA_ENCRYPT, - &true, sizeof (true)); - numpubattr++; - SETATTR(rsaPubKeyTemplate, numpubattr, CKA_VERIFY, - &true, sizeof (true)); - numpubattr++; - SETATTR(rsaPubKeyTemplate, numpubattr, CKA_WRAP, - &true, sizeof (true)); - numpubattr++; - - SETATTR(rsaPriKeyTemplate, numpriattr, CKA_TOKEN, - (storekey ? &true : &false), sizeof (CK_BBOOL)); - numpriattr++; - SETATTR(rsaPriKeyTemplate, numpriattr, CKA_PRIVATE, &true, - sizeof (true)); - numpriattr++; - SETATTR(rsaPriKeyTemplate, numpriattr, CKA_DECRYPT, &true, - sizeof (true)); - numpriattr++; - SETATTR(rsaPriKeyTemplate, numpriattr, CKA_SIGN, &true, - sizeof (true)); - numpriattr++; - SETATTR(rsaPriKeyTemplate, numpriattr, CKA_UNWRAP, &true, - sizeof (true)); - numpriattr++; - - - pubKey = CK_INVALID_HANDLE; - priKey = CK_INVALID_HANDLE; - ckrv = C_GenerateKeyPair(hSession, &keyGenMech, - rsaPubKeyTemplate, numpubattr, - rsaPriKeyTemplate, numpriattr, - &pubKey, &priKey); - if (ckrv != CKR_OK) { - SET_ERROR(kmfh, ckrv); - return (KMF_ERR_KEYGEN_FAILED); - } + if (ckrv != CKR_OK) + return (KMF_ERR_BAD_PARAMETER); privkey->kstype = KMF_KEYSTORE_PK11TOKEN; privkey->keyalg = KMF_RSA; @@ -1615,37 +1765,79 @@ KMFPK11_CreateKeypair(KMF_HANDLE_T handle, IDInput.Length = modulusLength; } else if (keytype == KMF_DSA) { - CK_MECHANISM keyGenMech = {CKM_DSA_KEY_PAIR_GEN, NULL, 0}; CK_BYTE *keyvalue; CK_ULONG valueLen; CK_ATTRIBUTE valattr[1]; - SETATTR(ckDsaPriKeyTemplate, 2, CKA_TOKEN, - (storekey ? &true : &false), sizeof (CK_BBOOL)); + /* Generate the DSA keypair */ + ckrv = gendsa_keypair(kmfh, storekey, &pubKey, &priKey); + if (ckrv != CKR_OK) + return (KMF_ERR_BAD_PARAMETER); + + privkey->kstype = KMF_KEYSTORE_PK11TOKEN; + privkey->keyalg = KMF_DSA; + privkey->keyclass = KMF_ASYM_PRI; + privkey->keyp = (void *)priKey; + + pubkey->kstype = KMF_KEYSTORE_PK11TOKEN; + pubkey->keyalg = KMF_DSA; + pubkey->keyclass = KMF_ASYM_PUB; + pubkey->keyp = (void *)pubKey; + + /* Get the Public Value to use as input for creating the ID */ SETATTR(valattr, 0, CKA_VALUE, NULL, &valueLen); - ckrv = C_GenerateKeyPair(hSession, &keyGenMech, - ckDsaPubKeyTemplate, - (sizeof (ckDsaPubKeyTemplate)/sizeof (CK_ATTRIBUTE)), - ckDsaPriKeyTemplate, - (sizeof (ckDsaPriKeyTemplate)/sizeof (CK_ATTRIBUTE)), - &pubKey, &priKey); + ckrv = C_GetAttributeValue(hSession, + (CK_OBJECT_HANDLE)pubKey, valattr, 1); + if (ckrv != CKR_OK) { + SET_ERROR(kmfh, ckrv); + return (KMF_ERR_BAD_PARAMETER); + } + + valueLen = valattr[0].ulValueLen; + keyvalue = malloc(valueLen); + if (keyvalue == NULL) + return (KMF_ERR_MEMORY); + + valattr[0].pValue = keyvalue; + ckrv = C_GetAttributeValue(hSession, + (CK_OBJECT_HANDLE)pubKey, valattr, 1); if (ckrv != CKR_OK) { SET_ERROR(kmfh, ckrv); - return (KMF_ERR_KEYGEN_FAILED); + free(keyvalue); + return (KMF_ERR_BAD_PARAMETER); } + IDInput.Data = keyvalue; + IDInput.Length = valueLen; + } else if (keytype == KMF_ECDSA) { + CK_BYTE *keyvalue; + CK_ULONG valueLen; + CK_ATTRIBUTE valattr[1]; + KMF_OID *eccoid = kmf_get_attr_ptr(KMF_ECC_CURVE_OID_ATTR, + attlist, numattr); + + if (eccoid == NULL) + return (KMF_ERR_BAD_PARAMETER); + + ckrv = genecc_keypair(kmfh, storekey, eccoid, + &pubKey, &priKey); + if (ckrv != CKR_OK) + return (KMF_ERR_BAD_PARAMETER); + privkey->kstype = KMF_KEYSTORE_PK11TOKEN; - privkey->keyalg = KMF_DSA; + privkey->keyalg = KMF_ECDSA; privkey->keyclass = KMF_ASYM_PRI; privkey->keyp = (void *)priKey; pubkey->kstype = KMF_KEYSTORE_PK11TOKEN; - pubkey->keyalg = KMF_DSA; + pubkey->keyalg = KMF_ECDSA; pubkey->keyclass = KMF_ASYM_PUB; pubkey->keyp = (void *)pubKey; - /* Get the Public Value to use as input for creating the ID */ + /* Get the EC_POINT to use as input for creating the ID */ + SETATTR(valattr, 0, CKA_EC_POINT, NULL, &valueLen); + ckrv = C_GetAttributeValue(hSession, (CK_OBJECT_HANDLE)pubKey, valattr, 1); if (ckrv != CKR_OK) { @@ -1812,12 +2004,17 @@ KMFPK11_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *keyp, KMF_DATA *tobesigned, KMF_DATA *output) { + KMF_RETURN rv = KMF_OK; CK_RV ckrv; KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; CK_SESSION_HANDLE hSession = kmfh->pk11handle; CK_MECHANISM mechanism; - PKCS_ALGORITHM_MAP *pAlgMap; + CK_MECHANISM_TYPE mechtype, hashmech; + CK_KEY_TYPE keytype; KMF_ALGORITHM_INDEX AlgId; + KMF_DATA hashData = {NULL, 0}; + uchar_t digest[1024]; + CK_ATTRIBUTE subprime = { CKA_SUBPRIME, NULL, 0 }; if (kmfh == NULL) return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */ @@ -1834,14 +2031,36 @@ KMFPK11_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *keyp, if (AlgId == KMF_ALGID_NONE) return (KMF_ERR_BAD_PARAMETER); - /* Map the Algorithm OID to a PKCS#11 mechanism */ - pAlgMap = pkcs_get_alg_map(KMF_ALGCLASS_SIGNATURE, - AlgId, PKCS_GetDefaultSignatureMode(AlgId)); - - if (pAlgMap == NULL) + /* Get the PKCS11 signing key type and mechtype */ + if (get_pk11_data(AlgId, &keytype, &mechtype, &hashmech, 0)) return (KMF_ERR_BAD_PARAMETER); - mechanism.mechanism = pAlgMap->pkcs_mechanism; + (void) memset(digest, 0, sizeof (digest)); + hashData.Data = digest; + hashData.Length = sizeof (digest); + rv = PKCS_DigestData(handle, hSession, hashmech, tobesigned, &hashData, + (mechtype == CKM_RSA_PKCS)); + if (rv) + return (rv); + + if (mechtype == CKM_DSA && hashmech == CKM_SHA256) { + /* + * FIPS 186-3 says that when signing with DSA + * the hash must be truncated to the size of the + * subprime. + */ + ckrv = C_GetAttributeValue(hSession, + (CK_OBJECT_HANDLE)keyp->keyp, + &subprime, 1); + if (ckrv != CKR_OK) { + SET_ERROR(kmfh, ckrv); + return (KMF_ERR_INTERNAL); + } + hashData.Length = subprime.ulValueLen; + } + + /* the mechtype from the 'get_pk11_info' refers to the signing */ + mechanism.mechanism = mechtype; mechanism.pParameter = NULL; mechanism.ulParameterLen = 0; @@ -1851,7 +2070,7 @@ KMFPK11_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *keyp, return (KMF_ERR_INTERNAL); } - ckrv = C_Sign(hSession, tobesigned->Data, tobesigned->Length, + ckrv = C_Sign(hSession, hashData.Data, hashData.Length, output->Data, (CK_ULONG *)&output->Length); if (ckrv != CKR_OK) { @@ -2069,6 +2288,8 @@ KMFPK11_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr, key->keyalg = KMF_RSA; else if (keytype == CKK_DSA) key->keyalg = KMF_DSA; + else if (keytype == CKK_EC) + key->keyalg = KMF_ECDSA; else { /* For asymmetric keys, we only support RSA and DSA */ rv = KMF_ERR_KEY_NOT_FOUND; @@ -2104,7 +2325,8 @@ KMFPK11_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; CK_SESSION_HANDLE hSession = kmfh->pk11handle; CK_MECHANISM mechanism; - PKCS_ALGORITHM_MAP *pAlgMap; + CK_MECHANISM_TYPE mechtype; + CK_KEY_TYPE keytype; KMF_ALGORITHM_INDEX AlgId; CK_ULONG out_len = 0, block_len = 0, total_decrypted = 0; uint8_t *in_data, *out_data; @@ -2126,13 +2348,10 @@ KMFPK11_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, return (KMF_ERR_BAD_PARAMETER); /* Map the Algorithm ID to a PKCS#11 mechanism */ - pAlgMap = pkcs_get_alg_map(KMF_ALGCLASS_SIGNATURE, - AlgId, PKCS_GetDefaultSignatureMode(AlgId)); - - if (pAlgMap == NULL) + if (get_pk11_data(AlgId, &keytype, &mechtype, NULL, 0)) return (KMF_ERR_BAD_PARAMETER); - mechanism.mechanism = pAlgMap->pkcs_mechanism; + mechanism.mechanism = mechtype; mechanism.pParameter = NULL; mechanism.ulParameterLen = 0; @@ -2390,6 +2609,64 @@ ret1: return (rv); } +static KMF_RETURN +get_raw_ec(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_EC_KEY *rawec) +{ + KMF_RETURN rv = KMF_OK; + CK_RV ckrv; + CK_SESSION_HANDLE sess = kmfh->pk11handle; + CK_ATTRIBUTE ec_attrs[2] = { + { CKA_EC_PARAMS, NULL, 0}, + { CKA_VALUE, NULL, 0} + }; + CK_ULONG count = sizeof (ec_attrs) / sizeof (CK_ATTRIBUTE); + int i; + + if ((ckrv = C_GetAttributeValue(sess, obj, + ec_attrs, 2)) != CKR_OK) { + SET_ERROR(kmfh, ckrv); + + /* Tell the caller know why the key data cannot be retrieved. */ + if (ckrv == CKR_ATTRIBUTE_SENSITIVE) + return (KMF_ERR_SENSITIVE_KEY); + else if (ckrv == CKR_KEY_UNEXTRACTABLE) + return (KMF_ERR_UNEXTRACTABLE_KEY); + return (KMF_ERR_INTERNAL); + } + for (i = 0; i < count; i++) { + if (ec_attrs[i].ulValueLen == (CK_ULONG)-1 || + ec_attrs[i].ulValueLen == 0) { + ec_attrs[i].ulValueLen = 0; + continue; + } + if ((ec_attrs[i].pValue = + malloc(ec_attrs[i].ulValueLen)) == NULL) { + rv = KMF_ERR_MEMORY; + goto end; + } + } + if ((ckrv = C_GetAttributeValue(sess, obj, + ec_attrs, count)) != CKR_OK) { + SET_ERROR(kmfh, ckrv); + rv = KMF_ERR_INTERNAL; + goto end; + } + + rawec->params.Data = ec_attrs[0].pValue; + rawec->params.Length = ec_attrs[0].ulValueLen; + rawec->value.val = ec_attrs[1].pValue; + rawec->value.len = ec_attrs[1].ulValueLen; + +end: + if (rv != KMF_OK) { + for (i = 0; i < count; i++) { + if (ec_attrs[i].pValue != NULL) + free(ec_attrs[i].pValue); + } + (void) memset(rawec, 0, sizeof (KMF_RAW_EC_KEY)); + } + return (rv); +} static KMF_RETURN get_raw_dsa(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_DSA_KEY *rawdsa) @@ -2544,6 +2821,9 @@ keyObj2RawKey(KMF_HANDLE_T handle, KMF_KEY_HANDLE *inkey, rkey->not_extractable = B_TRUE; rv = KMF_OK; } + } else if (inkey->keyalg == KMF_ECDSA) { + rv = get_raw_ec(kmfh, (CK_OBJECT_HANDLE)inkey->keyp, + &rkey->rawdata.ec); } else { rv = KMF_ERR_BAD_PARAMETER; } @@ -2569,6 +2849,9 @@ kmf2pk11keytype(KMF_KEY_ALG keyalg, CK_KEY_TYPE *type) case KMF_DSA: *type = CKK_DSA; break; + case KMF_ECDSA: + *type = CKK_EC; + break; case KMF_AES: *type = CKK_AES; break; @@ -2802,6 +3085,8 @@ KMFPK11_FindKey(KMF_HANDLE_T handle, keys[n].keyalg = KMF_RSA; } else if (keytype == CKK_DSA) { keys[n].keyalg = KMF_DSA; + } else if (keytype == CKK_EC) { + keys[n].keyalg = KMF_ECDSA; } else if (keytype == CKK_AES) { keys[n].keyalg = KMF_AES; keys[n].keyclass = @@ -2936,6 +3221,8 @@ store_raw_key(KMF_HANDLE_T handle, keytype = CKK_RSA; else if (rawkey->keytype == KMF_DSA) keytype = CKK_DSA; + else if (rawkey->keytype == KMF_ECDSA) + keytype = CKK_EC; else return (KMF_ERR_BAD_PARAMETER); @@ -2960,7 +3247,8 @@ store_raw_key(KMF_HANDLE_T handle, SETATTR(templ, i, CKA_KEY_TYPE, &keytype, sizeof (keytype)); i++; SETATTR(templ, i, CKA_TOKEN, &cktrue, sizeof (cktrue)); i++; SETATTR(templ, i, CKA_PRIVATE, &cktrue, sizeof (cktrue)); i++; - SETATTR(templ, i, CKA_DECRYPT, &cktrue, sizeof (cktrue)); i++; + if (keytype != CKK_EC) + SETATTR(templ, i, CKA_DECRYPT, &cktrue, sizeof (cktrue)); i++; cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr); if (cert != NULL) { @@ -3107,7 +3395,7 @@ store_raw_key(KMF_HANDLE_T handle, rawkey->rawdata.rsa.coef.len); i++; } - } else { + } else if (keytype == CKK_DSA) { SETATTR(templ, i, CKA_PRIME, rawkey->rawdata.dsa.prime.val, rawkey->rawdata.dsa.prime.len); @@ -3124,6 +3412,19 @@ store_raw_key(KMF_HANDLE_T handle, rawkey->rawdata.dsa.value.val, rawkey->rawdata.dsa.value.len); i++; + } else if (keytype == CKK_EC) { + SETATTR(templ, i, CKA_SIGN, &cktrue, sizeof (cktrue)); + i++; + SETATTR(templ, i, CKA_DERIVE, &cktrue, sizeof (cktrue)); + i++; + SETATTR(templ, i, CKA_VALUE, + rawkey->rawdata.ec.value.val, + rawkey->rawdata.ec.value.len); + i++; + SETATTR(templ, i, CKA_EC_PARAMS, + rawkey->rawdata.ec.params.Data, + rawkey->rawdata.ec.params.Length); + i++; } ckrv = C_CreateObject(kmfh->pk11handle, templ, i, &keyobj); @@ -3525,176 +3826,6 @@ end: } static KMF_RETURN -create_pk11_session(CK_SESSION_HANDLE *sessionp, CK_MECHANISM_TYPE wanted_mech, - CK_FLAGS wanted_flags) -{ - CK_RV rv; - KMF_RETURN kmf_rv = KMF_OK; - CK_SLOT_ID_PTR pSlotList; - CK_ULONG pulCount; - CK_MECHANISM_INFO info; - int i; - - rv = C_Initialize(NULL); - if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) { - kmf_rv = KMF_ERR_UNINITIALIZED; - goto out; - } - - rv = C_GetSlotList(0, NULL, &pulCount); - if (rv != CKR_OK) { - kmf_rv = KMF_ERR_UNINITIALIZED; - goto out; - } - - pSlotList = (CK_SLOT_ID_PTR) malloc(pulCount * sizeof (CK_SLOT_ID)); - if (pSlotList == NULL) { - kmf_rv = KMF_ERR_MEMORY; - goto out; - } - - rv = C_GetSlotList(0, pSlotList, &pulCount); - if (rv != CKR_OK) { - kmf_rv = KMF_ERR_UNINITIALIZED; - goto out; - } - - for (i = 0; i < pulCount; i++) { - rv = C_GetMechanismInfo(pSlotList[i], wanted_mech, &info); - if (rv == CKR_OK && (info.flags & wanted_flags)) - break; - } - if (i < pulCount) { - rv = C_OpenSession(pSlotList[i], CKF_SERIAL_SESSION, - NULL, NULL, sessionp); - - if (rv != CKR_OK) { - kmf_rv = KMF_ERR_UNINITIALIZED; - } - } else { - kmf_rv = KMF_ERR_UNINITIALIZED; - } - -out: - if (pSlotList != NULL) - free(pSlotList); - return (kmf_rv); - -} -static KMF_RETURN -verify_data(KMF_HANDLE_T handle, - KMF_ALGORITHM_INDEX AlgorithmId, - KMF_X509_SPKI *keyp, - KMF_DATA *data, - KMF_DATA *signed_data) -{ - KMF_RETURN ret; - PKCS_ALGORITHM_MAP *pAlgMap = NULL; - CK_RV ckRv; - CK_MECHANISM ckMechanism; - CK_OBJECT_HANDLE ckKeyHandle; - KMF_BOOL bTempKey; - KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; - CK_SESSION_HANDLE ckSession = NULL; - - if (AlgorithmId == KMF_ALGID_NONE) - return (KMF_ERR_BAD_ALGORITHM); - - pAlgMap = pkcs_get_alg_map(KMF_ALGCLASS_SIGNATURE, - AlgorithmId, PKCS_GetDefaultSignatureMode(AlgorithmId)); - - if (!pAlgMap) - return (KMF_ERR_BAD_ALGORITHM); - - ret = create_pk11_session(&ckSession, pAlgMap->pkcs_mechanism, - CKF_VERIFY); - if (ret != KMF_OK) - return (ret); - - /* Fetch the verifying key */ - ret = PKCS_AcquirePublicKeyHandle(ckSession, keyp, - pAlgMap->key_type, &ckKeyHandle, &bTempKey); - - if (ret != KMF_OK) { - return (ret); - } - - ckMechanism.mechanism = pAlgMap->pkcs_mechanism; - ckMechanism.pParameter = NULL; - ckMechanism.ulParameterLen = 0; - - ckRv = C_VerifyInit(ckSession, &ckMechanism, ckKeyHandle); - if (ckRv != CKR_OK) { - if (bTempKey) - (void) C_DestroyObject(ckSession, ckKeyHandle); - SET_ERROR(kmfh, ckRv); - ret = KMF_ERR_INTERNAL; - goto cleanup; - } - - ckRv = C_Verify(ckSession, (CK_BYTE *)data->Data, - (CK_ULONG)data->Length, (CK_BYTE *)signed_data->Data, - (CK_ULONG)signed_data->Length); - - if (ckRv != CKR_OK) { - SET_ERROR(kmfh, ckRv); - ret = KMF_ERR_INTERNAL; - } - -cleanup: - if (bTempKey) - (void) C_DestroyObject(ckSession, ckKeyHandle); - - (void) C_CloseSession(ckSession); - - return (ret); -} - -KMF_RETURN -KMFPK11_VerifyDataWithCert(KMF_HANDLE_T handle, - KMF_ALGORITHM_INDEX algid, KMF_DATA *indata, - KMF_DATA *insig, KMF_DATA *SignerCertData) -{ - KMF_RETURN ret = KMF_OK; - KMF_X509_CERTIFICATE *SignerCert = NULL; - KMF_X509_SPKI *pubkey; - - if (handle == NULL || indata == NULL || - indata->Data == NULL || indata->Length == 0 || - insig == NULL|| insig->Data == NULL || insig->Length == 0 || - SignerCertData == NULL || SignerCertData->Data == NULL || - SignerCertData->Length == 0) - return (KMF_ERR_BAD_PARAMETER); - - /* Decode the signer cert so we can get the SPKI data */ - ret = DerDecodeSignedCertificate(SignerCertData, &SignerCert); - if (ret != KMF_OK) - goto cleanup; - - /* Get the public key info from the signer certificate */ - pubkey = &SignerCert->certificate.subjectPublicKeyInfo; - - /* If no algorithm specified, use the certs signature algorithm */ - if (algid == KMF_ALGID_NONE) { - algid = x509_algoid_to_algid(CERT_ALG_OID(SignerCert)); - } - - if (algid == KMF_ALGID_NONE) { - ret = KMF_ERR_BAD_ALGORITHM; - } else { - ret = verify_data(handle, algid, pubkey, indata, insig); - } - -cleanup: - if (SignerCert) { - kmf_free_signed_cert(SignerCert); - free(SignerCert); - } - - return (ret); -} - -static KMF_RETURN create_generic_secret_key(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist, CK_OBJECT_HANDLE *key) { |