diff options
Diffstat (limited to 'providers/implementations/kdfs')
-rw-r--r-- | providers/implementations/kdfs/x942kdf.c | 152 |
1 files changed, 119 insertions, 33 deletions
diff --git a/providers/implementations/kdfs/x942kdf.c b/providers/implementations/kdfs/x942kdf.c index f19e014927..31a69a096e 100644 --- a/providers/implementations/kdfs/x942kdf.c +++ b/providers/implementations/kdfs/x942kdf.c @@ -39,11 +39,12 @@ typedef struct { PROV_DIGEST digest; unsigned char *secret; size_t secret_len; - unsigned char *ukm; - size_t ukm_len; + unsigned char *partyuinfo, *partyvinfo, *supp_pubinfo, *supp_privinfo; + size_t partyuinfo_len, partyvinfo_len, supp_pubinfo_len, supp_privinfo_len; size_t dkm_len; const unsigned char *cek_oid; size_t cek_oid_len; + int use_keybits; } KDF_X942; /* @@ -109,14 +110,23 @@ static int DER_w_keyinfo(WPACKET *pkt, static int der_encode_sharedinfo(WPACKET *pkt, unsigned char *buf, size_t buflen, const unsigned char *der_oid, size_t der_oidlen, - const unsigned char *ukm, size_t ukmlen, + const unsigned char *partyu, size_t partyulen, + const unsigned char *partyv, size_t partyvlen, + const unsigned char *supp_pub, size_t supp_publen, + const unsigned char *supp_priv, size_t supp_privlen, uint32_t keylen_bits, unsigned char **pcounter) { return (buf != NULL ? WPACKET_init_der(pkt, buf, buflen) : WPACKET_init_null_der(pkt)) && ossl_DER_w_begin_sequence(pkt, -1) - && ossl_DER_w_octet_string_uint32(pkt, 2, keylen_bits) - && (ukm == NULL || ossl_DER_w_octet_string(pkt, 0, ukm, ukmlen)) + && (supp_priv == NULL + || ossl_DER_w_octet_string(pkt, 3, supp_priv, supp_privlen)) + && (supp_pub == NULL + || ossl_DER_w_octet_string(pkt, 2, supp_pub, supp_publen)) + && (keylen_bits == 0 + || ossl_DER_w_octet_string_uint32(pkt, 2, keylen_bits)) + && (partyv == NULL || ossl_DER_w_octet_string(pkt, 1, partyv, partyvlen)) + && (partyu == NULL || ossl_DER_w_octet_string(pkt, 0, partyu, partyulen)) && DER_w_keyinfo(pkt, der_oid, der_oidlen, pcounter) && ossl_DER_w_end_sequence(pkt, -1) && WPACKET_finish(pkt); @@ -125,28 +135,48 @@ static int der_encode_sharedinfo(WPACKET *pkt, unsigned char *buf, size_t buflen /* * Encode the other info structure. * - * RFC2631 Section 2.1.2 Contains the following definition for otherinfo + * The ANS X9.42-2003 standard uses OtherInfo: * * OtherInfo ::= SEQUENCE { * keyInfo KeySpecificInfo, - * partyAInfo [0] OCTET STRING OPTIONAL, - * suppPubInfo [2] OCTET STRING + * partyUInfo [0] OCTET STRING OPTIONAL, + * partyVInfo [1] OCTET STRING OPTIONAL, + * suppPubInfo [2] OCTET STRING OPTIONAL, + * suppPrivInfo [3] OCTET STRING OPTIONAL * } - * Note suppPubInfo is the key length (in bits) (stored into 4 bytes) - * * * KeySpecificInfo ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * counter OCTET STRING SIZE (4..4) * } * + * RFC2631 Section 2.1.2 Contains the following definition for OtherInfo + * + * OtherInfo ::= SEQUENCE { + * keyInfo KeySpecificInfo, + * partyAInfo [0] OCTET STRING OPTIONAL, + * suppPubInfo [2] OCTET STRING + * } + * Where suppPubInfo is the key length (in bits) (stored into 4 bytes) + * +} + * * |keylen| is the length (in bytes) of the generated KEK. It is stored into - * suppPubInfo (in bits). + * suppPubInfo (in bits). It is ignored if the value is 0. * |cek_oid| The oid of the key wrapping algorithm. * |cek_oidlen| The length (in bytes) of the key wrapping algorithm oid, - * |ukm| is the optional user keying material that is stored into partyAInfo. It + * |partyu| is the optional public info contributed by the initiator. It + * can be NULL. (It is also used as the ukm by CMS). + * |partyu_len| is the |partyu| length (in bytes). + * |partyv| is the optional public info contributed by the responder. It * can be NULL. - * |ukmlen| is the user keying material length (in bytes). + * |partyv_len| is the |partyv| length (in bytes). + * |supp_pub| is the optional additional, mutually-known public information. It + * can be NULL. |keylen| should be 0 if this is not NULL. + * |supp_pub_len| is the |supp_pub| length (in bytes). + * |supp_priv| is the optional additional, mutually-known private information. It + * can be NULL. + * |supp_priv_len| is the |supp_priv| length (in bytes). * |der| is the returned encoded data. It must be freed by the caller. * |der_len| is the returned size of the encoded data. * |out_ctr| returns a pointer to the counter data which is embedded inside the @@ -155,11 +185,15 @@ static int der_encode_sharedinfo(WPACKET *pkt, unsigned char *buf, size_t buflen * Returns: 1 if successfully encoded, or 0 otherwise. * Assumptions: |der|, |der_len| & |out_ctr| are not NULL. */ -static int x942_encode_otherinfo(size_t keylen, - const unsigned char *cek_oid, size_t cek_oidlen, - const unsigned char *ukm, size_t ukmlen, - unsigned char **der, size_t *der_len, - unsigned char **out_ctr) +static int +x942_encode_otherinfo(size_t keylen, + const unsigned char *cek_oid, size_t cek_oidlen, + const unsigned char *partyu, size_t partyu_len, + const unsigned char *partyv, size_t partyv_len, + const unsigned char *supp_pub, size_t supp_pub_len, + const unsigned char *supp_priv, size_t supp_priv_len, + unsigned char **der, size_t *der_len, + unsigned char **out_ctr) { int ret = 0; unsigned char *pcounter = NULL, *der_buf = NULL; @@ -173,7 +207,9 @@ static int x942_encode_otherinfo(size_t keylen, keylen_bits = 8 * keylen; /* Calculate the size of the buffer */ - if (!der_encode_sharedinfo(&pkt, NULL, 0, cek_oid, cek_oidlen, ukm, ukmlen, + if (!der_encode_sharedinfo(&pkt, NULL, 0, cek_oid, cek_oidlen, + partyu, partyu_len, partyv, partyv_len, + supp_pub, supp_pub_len, supp_priv, supp_priv_len, keylen_bits, NULL) || !WPACKET_get_total_written(&pkt, &der_buflen)) goto err; @@ -184,7 +220,9 @@ static int x942_encode_otherinfo(size_t keylen, goto err; /* Encode into the buffer */ if (!der_encode_sharedinfo(&pkt, der_buf, der_buflen, cek_oid, cek_oidlen, - ukm, ukmlen, keylen_bits, &pcounter)) + partyu, partyu_len, partyv, partyv_len, + supp_pub, supp_pub_len, supp_priv, supp_priv_len, + keylen_bits, &pcounter)) goto err; /* * Since we allocated the exact size required, the buffer should point to the @@ -287,6 +325,7 @@ static void *x942kdf_new(void *provctx) if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); ctx->provctx = provctx; + ctx->use_keybits = 1; return ctx; } @@ -297,9 +336,13 @@ static void x942kdf_reset(void *vctx) ossl_prov_digest_reset(&ctx->digest); OPENSSL_clear_free(ctx->secret, ctx->secret_len); - OPENSSL_clear_free(ctx->ukm, ctx->ukm_len); + OPENSSL_clear_free(ctx->partyuinfo, ctx->partyuinfo_len); + OPENSSL_clear_free(ctx->partyvinfo, ctx->partyvinfo_len); + OPENSSL_clear_free(ctx->supp_pubinfo, ctx->supp_pubinfo_len); + OPENSSL_clear_free(ctx->supp_privinfo, ctx->supp_privinfo_len); memset(ctx, 0, sizeof(*ctx)); ctx->provctx = provctx; + ctx->use_keybits = 1; } static void x942kdf_free(void *vctx) @@ -348,6 +391,15 @@ static int x942kdf_derive(void *vctx, unsigned char *key, size_t keylen) if (!ossl_prov_is_running()) return 0; + /* + * These 2 options encode to the same field so only one of them should be + * active at once. + */ + if (ctx->use_keybits && ctx->supp_pubinfo != NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PUBINFO); + return 0; + } + if (ctx->secret == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET); return 0; @@ -361,18 +413,21 @@ static int x942kdf_derive(void *vctx, unsigned char *key, size_t keylen) ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CEK_ALG); return 0; } - if (ctx->ukm != NULL && ctx->ukm_len >= X942KDF_MAX_INLEN) { + if (ctx->partyuinfo != NULL && ctx->partyuinfo_len >= X942KDF_MAX_INLEN) { /* - * Note the ukm length MUST be 512 bits. + * Note the ukm length MUST be 512 bits if it is used. * For backwards compatibility the old check is being done. */ - ERR_raise(ERR_LIB_PROV, PROV_R_INAVLID_UKM_LENGTH); + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_UKM_LENGTH); return 0; } /* generate the otherinfo der */ - if (!x942_encode_otherinfo(ctx->dkm_len, + if (!x942_encode_otherinfo(ctx->use_keybits ? ctx->dkm_len : 0, ctx->cek_oid, ctx->cek_oid_len, - ctx->ukm, ctx->ukm_len, + ctx->partyuinfo, ctx->partyuinfo_len, + ctx->partyvinfo, ctx->partyvinfo_len, + ctx->supp_pubinfo, ctx->supp_pubinfo_len, + ctx->supp_privinfo, ctx->supp_privinfo_len, &der, &der_len, &ctr)) { ERR_raise(ERR_LIB_PROV, PROV_R_BAD_ENCODING); return 0; @@ -394,16 +449,42 @@ static int x942kdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx)) return 0; - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET)) != NULL - || (p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL) - if (!x942kdf_set_buffer(&ctx->secret, &ctx->secret_len, p)) - return 0; + p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET); + if (p == NULL) + p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY); + if (p != NULL && !x942kdf_set_buffer(&ctx->secret, &ctx->secret_len, p)) + return 0; + + p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_X942_PARTYUINFO); + if (p == NULL) + p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_UKM); + if (p != NULL + && !x942kdf_set_buffer(&ctx->partyuinfo, &ctx->partyuinfo_len, p)) + return 0; - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_UKM)) != NULL) - if (!x942kdf_set_buffer(&ctx->ukm, &ctx->ukm_len, p)) + p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_X942_PARTYVINFO); + if (p != NULL + && !x942kdf_set_buffer(&ctx->partyvinfo, &ctx->partyvinfo_len, p)) + return 0; + + p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_X942_USE_KEYBITS); + if (p != NULL && !OSSL_PARAM_get_int(p, &ctx->use_keybits)) + return 0; + + p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_X942_SUPP_PUBINFO); + if (p != NULL) { + if (!x942kdf_set_buffer(&ctx->supp_pubinfo, &ctx->supp_pubinfo_len, p)) return 0; + ctx->use_keybits = 0; + } + + p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_X942_SUPP_PRIVINFO); + if (p != NULL + && !x942kdf_set_buffer(&ctx->supp_privinfo, &ctx->supp_privinfo_len, p)) + return 0; - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_CEK_ALG)) != NULL) { + p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_CEK_ALG); + if (p != NULL) { if (p->data_type != OSSL_PARAM_UTF8_STRING) return 0; pq = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_PROPERTIES); @@ -430,6 +511,11 @@ static const OSSL_PARAM *x942kdf_settable_ctx_params(ossl_unused void *provctx) OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SECRET, NULL, 0), OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0), OSSL_PARAM_octet_string(OSSL_KDF_PARAM_UKM, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_X942_PARTYUINFO, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_X942_PARTYVINFO, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_X942_SUPP_PUBINFO, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_X942_SUPP_PRIVINFO, NULL, 0), + OSSL_PARAM_int(OSSL_KDF_PARAM_X942_USE_KEYBITS, NULL), OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CEK_ALG, NULL, 0), OSSL_PARAM_END }; |