From f676d00009b9e7cb998ee1b1165ffb0c0838e7fe Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Mon, 11 Jul 2016 12:29:12 +0200 Subject: [PATCH] EC key generation, extract public and get_bit_length Change-Id: I55f22032778eaf6eaeb5d598eec1fe94fe684765 --- api/yaca/yaca_key.h | 9 ++++ api/yaca/yaca_types.h | 82 +++++++++++++++++++++++++++++ src/key.c | 143 ++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 212 insertions(+), 22 deletions(-) diff --git a/api/yaca/yaca_key.h b/api/yaca/yaca_key.h index c877766..f5de839 100755 --- a/api/yaca/yaca_key.h +++ b/api/yaca/yaca_key.h @@ -54,6 +54,8 @@ extern "C" { * @return #YACA_ERROR_NONE on success, negative on error * @retval #YACA_ERROR_NONE Successful * @retval #YACA_ERROR_INVALID_PARAMETER Either of the params is NULL + * + * @see #yaca_key_type_e */ int yaca_key_get_type(const yaca_key_h key, yaca_key_type_e *key_type); @@ -62,6 +64,8 @@ int yaca_key_get_type(const yaca_key_h key, yaca_key_type_e *key_type); * * @since_tizen 3.0 * + * @remarks For elliptic curves @a key_bit_len returns values from #yaca_key_bit_length_ec_e + * * @param[in] key Key which length we return * @param[out] key_bit_len Key length in bits * @@ -69,6 +73,9 @@ int yaca_key_get_type(const yaca_key_h key, yaca_key_type_e *key_type); * @retval #YACA_ERROR_NONE Successful * @retval #YACA_ERROR_INVALID_PARAMETER Either of the params is NULL * @retval #YACA_ERROR_INTERNAL Internal error + * + * @see #yaca_key_bit_length_e + * @see #yaca_key_bit_length_ec_e */ int yaca_key_get_bit_length(const yaca_key_h key, size_t *key_bit_len); @@ -194,6 +201,7 @@ int yaca_key_export(const yaca_key_h key, * @remarks Supported key lengths: * - RSA: length >= 256bits * - DSA: length >= 512bits, multiple of 64 + * - EC: @a key_bit_len takes values from #yaca_key_bit_length_ec_e * * @remarks The @a key should be released using yaca_key_destroy() * @@ -210,6 +218,7 @@ int yaca_key_export(const yaca_key_h key, * * @see #yaca_key_type_e * @see #yaca_key_bit_length_e + * @see #yaca_key_bit_length_ec_e * @see yaca_key_destroy() */ int yaca_key_generate(yaca_key_type_e key_type, diff --git a/api/yaca/yaca_types.h b/api/yaca/yaca_types.h index cd78f88..8c3a5b1 100755 --- a/api/yaca/yaca_types.h +++ b/api/yaca/yaca_types.h @@ -33,6 +33,68 @@ extern "C" { * @{ */ +/* The format of the unsigned int used to indicate key_bit_len is as follows: + * + * Bits indicating a type: + * bits 31-30 (2 bits) indicate key_length type: + * 00(0) - regular type for RSA, DSA and DH + * 01(1) - elliptic curve + * remaining combinations reserved + * + * Bits for a regular type: + * bits 29-0 (30 bits) indicate length of the key in bits + * + * Bits for an elliptic curve type: + * bits 29-26 (4 bits) indicate type of an elliptic curve: + * 0000(0) - X9.62 Prime + * 0001(1) - SECP + * 0010(2) - SECT + * 0011(3) - Brainpool + * remaining combinations reserved (c2pnb, c2tnb, c2onb...) + * bits 25-22 (4 bits) indicate a letter: + * 0000(0) - v + * 0001(1) - r + * 0010(2) - k + * 0011(3) - t + * remaining combinations reserved (w...) + * bits 21-18 (4 bits) indicate a number: + * 0000(0) - 1 + * 0001(1) - 2 + * 0010(2) - 3 + * 0011(3) - 4 + * remaining combinations reserved + * bits 17-0 (18 bits) - length of the prime field in bits + * + * For now this is mostly used for elliptic curves. For any other keys key_bit_len can be + * passed just as a number of bits (2 most significant bits set to 00, 30 bits for bit length). + * + * For elliptic curves don't use those defines directly, use enums in yaca_key_bit_length_ec_e. + * Not all combinations are valid and other valid combinations are not guaranteed to be + * implemented (they most surely aren't). + */ + +/** @cond Don't include those defines in doxygen, they are not to be used directly */ +#define YACA_KEY_LEN_TYPE_MASK (3U << 30) + +#define YACA_KEY_LEN_TYPE_REGULAR (0U << 30) +#define YACA_KEY_LEN_TYPE_EC (1U << 30) + +#define YACA_KEY_LEN_EC_PRIME (0U << 26) +#define YACA_KEY_LEN_EC_SECP (1U << 26) +#define YACA_KEY_LEN_EC_SECT (2U << 26) +#define YACA_KEY_LEN_EC_BRAINPOOL (3U << 26) + +#define YACA_KEY_LEN_EC_V (0U << 22) +#define YACA_KEY_LEN_EC_R (1U << 22) +#define YACA_KEY_LEN_EC_K (2U << 22) +#define YACA_KEY_LEN_EC_T (3U << 22) + +#define YACA_KEY_LEN_EC_1 (0U << 18) +#define YACA_KEY_LEN_EC_2 (1U << 18) +#define YACA_KEY_LEN_EC_3 (2U << 18) +#define YACA_KEY_LEN_EC_4 (3U << 18) +/** @endcond */ + /** * @brief The context handle. * @@ -152,6 +214,26 @@ typedef enum { } yaca_key_bit_length_e; /** + * @brief Enumeration of YACA elliptic curve types with their bit lengths. + * It's meant to be passed or returned as a @a key_bit_len param + * in appropriate functions when dealing with elliptic curves. + * + * @since_tizen 3.0 + */ +typedef enum { + /** Elliptic curve prime192v1 */ + YACA_KEY_LENGTH_EC_PRIME192V1 = YACA_KEY_LEN_TYPE_EC | YACA_KEY_LEN_EC_PRIME | YACA_KEY_LEN_EC_V | YACA_KEY_LEN_EC_1 | 192U, + /** Elliptic curve prime256v1 */ + YACA_KEY_LENGTH_EC_PRIME256V1 = YACA_KEY_LEN_TYPE_EC | YACA_KEY_LEN_EC_PRIME | YACA_KEY_LEN_EC_V | YACA_KEY_LEN_EC_1 | 256U, + /** Elliptic curve secp256k1 */ + YACA_KEY_LENGTH_EC_SECP256K1 = YACA_KEY_LEN_TYPE_EC | YACA_KEY_LEN_EC_SECP | YACA_KEY_LEN_EC_K | YACA_KEY_LEN_EC_1 | 256U, + /** Elliptic curve secp384r1 */ + YACA_KEY_LENGTH_EC_SECP384R1 = YACA_KEY_LEN_TYPE_EC | YACA_KEY_LEN_EC_SECP | YACA_KEY_LEN_EC_R | YACA_KEY_LEN_EC_1 | 384U, + /** Elliptic curve secp521r1 */ + YACA_KEY_LENGTH_EC_SECP521R1 = YACA_KEY_LEN_TYPE_EC | YACA_KEY_LEN_EC_SECP | YACA_KEY_LEN_EC_R | YACA_KEY_LEN_EC_1 | 521U +} yaca_key_bit_length_ec_e; + +/** * @brief Enumeration of YACA message digest algorithms. * * @since_tizen 3.0 diff --git a/src/key.c b/src/key.c index 706e9dc..b2df812 100644 --- a/src/key.c +++ b/src/key.c @@ -37,9 +37,23 @@ #include #include #include +#include #include "internal.h" +const static struct { + size_t key_bit_len_ec; + int nid; +} EC_NID_PAIRS[] = { + {YACA_KEY_LENGTH_EC_PRIME192V1, NID_X9_62_prime192v1}, + {YACA_KEY_LENGTH_EC_PRIME256V1, NID_X9_62_prime256v1}, + {YACA_KEY_LENGTH_EC_SECP256K1, NID_secp256k1}, + {YACA_KEY_LENGTH_EC_SECP384R1, NID_secp384r1}, + {YACA_KEY_LENGTH_EC_SECP521R1, NID_secp521r1} +}; + +const static size_t EC_NID_PAIRS_SIZE = sizeof(EC_NID_PAIRS) / sizeof(EC_NID_PAIRS[0]); + struct openssl_password_data { bool password_requested; const char *password; @@ -739,6 +753,9 @@ int generate_simple(struct yaca_key_simple_s **out, size_t key_bit_len) { assert(out != NULL); + if (key_bit_len % 8 != 0) + return YACA_ERROR_INVALID_PARAMETER; + int ret; struct yaca_key_simple_s *nk; size_t key_byte_len = key_bit_len / 8; @@ -811,6 +828,38 @@ exit: return ret; } +int convert_ec_to_nid(size_t key_bit_len_ec, int *nid) +{ + assert(nid != NULL); + + size_t i; + + for (i = 0; i < EC_NID_PAIRS_SIZE; ++i) { + if (EC_NID_PAIRS[i].key_bit_len_ec == key_bit_len_ec) { + *nid = EC_NID_PAIRS[i].nid; + return YACA_ERROR_NONE; + } + } + + return YACA_ERROR_INVALID_PARAMETER; +} + +size_t convert_nid_to_ec(int nid, size_t *key_bit_len_ec) +{ + assert(key_bit_len_ec != NULL); + + size_t i; + + for (i = 0; i < EC_NID_PAIRS_SIZE; ++i) { + if (EC_NID_PAIRS[i].nid == nid) { + *key_bit_len_ec = EC_NID_PAIRS[i].key_bit_len_ec; + return YACA_ERROR_NONE; + } + } + + return YACA_ERROR_INVALID_PARAMETER; +} + int generate_evp(struct yaca_key_evp_s **out, yaca_key_type_e key_type, size_t key_bit_len) { assert(out != NULL); @@ -825,29 +874,40 @@ int generate_evp(struct yaca_key_evp_s **out, yaca_key_type_e key_type, size_t k EVP_PKEY *params = NULL; struct yaca_key_evp_s *nk; - switch(key_type) { + switch (key_type) { case YACA_KEY_TYPE_RSA_PRIV: - assert(key_bit_len % 8 == 0); + if ((key_bit_len & YACA_KEY_LEN_TYPE_MASK) != YACA_KEY_LEN_TYPE_REGULAR || + key_bit_len % 8 != 0) + return YACA_ERROR_INVALID_PARAMETER; id = EVP_PKEY_RSA; do_params = false; break; case YACA_KEY_TYPE_DSA_PRIV: - assert(key_bit_len % 8 == 0); - - /* Openssl generates 512-bit key for key lengths smaller than 512. It also - * rounds key size to multiplication of 64. */ - if (key_bit_len < 512 || key_bit_len % 64 != 0) + if ((key_bit_len & YACA_KEY_LEN_TYPE_MASK) != YACA_KEY_LEN_TYPE_REGULAR || + /* Openssl generates 512-bit key for key lengths smaller than 512. It also + * rounds key size to multiplication of 64. */ + key_bit_len < 512 || key_bit_len % 64 != 0) return YACA_ERROR_INVALID_PARAMETER; + id = EVP_PKEY_DSA; do_params = true; break; case YACA_KEY_TYPE_DH_PRIV: - assert(key_bit_len % 8 == 0); + if ((key_bit_len & YACA_KEY_LEN_TYPE_MASK) != YACA_KEY_LEN_TYPE_REGULAR || + key_bit_len % 8 != 0) + return YACA_ERROR_INVALID_PARAMETER; id = EVP_PKEY_DH; do_params = true; break; + case YACA_KEY_TYPE_EC_PRIV: + if ((key_bit_len & YACA_KEY_LEN_TYPE_MASK) != YACA_KEY_LEN_TYPE_EC) + return YACA_ERROR_INVALID_PARAMETER; + + id = EVP_PKEY_EC; + do_params = true; + break; default: return YACA_ERROR_INVALID_PARAMETER; } @@ -871,19 +931,30 @@ int generate_evp(struct yaca_key_evp_s **out, yaca_key_type_e key_type, size_t k goto exit; } - switch(id) { + switch (id) { case EVP_PKEY_DSA: ret = EVP_PKEY_CTX_set_dsa_paramgen_bits(pctx, key_bit_len); break; case EVP_PKEY_DH: ret = EVP_PKEY_CTX_set_dh_paramgen_prime_len(pctx, key_bit_len); break; + case EVP_PKEY_EC: { + int nid; + ret = convert_ec_to_nid(key_bit_len, &nid); + if (ret != YACA_ERROR_NONE) + goto exit; + ret = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, nid); + if (ret == 1) + ret = EVP_PKEY_CTX_set_ec_param_enc(pctx, OPENSSL_EC_NAMED_CURVE); + break; + } default: /* We shouldn't be here */ assert(false); ret = YACA_ERROR_INTERNAL; goto exit; } + if (ret != 1) { ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); @@ -983,6 +1054,8 @@ struct yaca_key_evp_s *key_get_evp(const yaca_key_h key) case YACA_KEY_TYPE_DSA_PRIV: case YACA_KEY_TYPE_DH_PUB: case YACA_KEY_TYPE_DH_PRIV: + case YACA_KEY_TYPE_EC_PUB: + case YACA_KEY_TYPE_EC_PRIV: k = (struct yaca_key_evp_s *)key; /* sanity check */ @@ -1068,16 +1141,44 @@ API int yaca_key_get_bit_length(const yaca_key_h key, size_t *key_bit_len) if (evp_key != NULL) { int ret; - // TODO: handle ECC keys when they're implemented - ret = EVP_PKEY_bits(evp_key->evp); - if (ret <= 0) { - ret = YACA_ERROR_INTERNAL; - ERROR_DUMP(ret); - return ret; - } + switch (evp_key->key.type) { + case YACA_KEY_TYPE_RSA_PRIV: + case YACA_KEY_TYPE_RSA_PUB: + case YACA_KEY_TYPE_DSA_PRIV: + case YACA_KEY_TYPE_DSA_PUB: + case YACA_KEY_TYPE_DH_PRIV: + case YACA_KEY_TYPE_DH_PUB: + ret = EVP_PKEY_bits(evp_key->evp); + if (ret <= 0) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + return ret; + } - *key_bit_len = ret; - return YACA_ERROR_NONE; + *key_bit_len = ret; + return YACA_ERROR_NONE; + case YACA_KEY_TYPE_EC_PRIV: + case YACA_KEY_TYPE_EC_PUB: { + assert(EVP_PKEY_type(evp_key->evp->type) == EVP_PKEY_EC); + + const EC_KEY *eck = EVP_PKEY_get0(evp_key->evp); + const EC_GROUP *ecg = EC_KEY_get0_group(eck); + int flags = EC_GROUP_get_asn1_flag(ecg); + int nid; + + if (!(flags & OPENSSL_EC_NAMED_CURVE)) + /* This is case of a custom (not named) curve, that can happen when someone + imports such a key into YACA. There is nothing that can be returned here */ + return YACA_ERROR_INVALID_PARAMETER; + + nid = EC_GROUP_get_curve_name(ecg); + return convert_nid_to_ec(nid, key_bit_len); + } + default: + /* We shouldn't be here */ + assert(false); + return YACA_ERROR_INTERNAL; + } } return YACA_ERROR_INVALID_PARAMETER; @@ -1163,7 +1264,7 @@ API int yaca_key_generate(yaca_key_type_e key_type, struct yaca_key_simple_s *nk_simple = NULL; struct yaca_key_evp_s *nk_evp = NULL; - if (key == NULL || key_bit_len == 0 || key_bit_len % 8 != 0) + if (key == NULL || key_bit_len == 0) return YACA_ERROR_INVALID_PARAMETER; switch (key_type) { @@ -1177,10 +1278,9 @@ API int yaca_key_generate(yaca_key_type_e key_type, case YACA_KEY_TYPE_RSA_PRIV: case YACA_KEY_TYPE_DSA_PRIV: case YACA_KEY_TYPE_DH_PRIV: + case YACA_KEY_TYPE_EC_PRIV: ret = generate_evp(&nk_evp, key_type, key_bit_len); break; - case YACA_KEY_TYPE_EC_PRIV: - //TODO NOT_IMPLEMENTED default: return YACA_ERROR_INVALID_PARAMETER; } @@ -1197,7 +1297,6 @@ API int yaca_key_generate(yaca_key_type_e key_type, } return YACA_ERROR_NONE; - } API int yaca_key_extract_public(const yaca_key_h prv_key, yaca_key_h *pub_key) -- 2.7.4