diff options
Diffstat (limited to 'src/lib/libcrypto/ec/ec_pmeth.c')
| -rw-r--r-- | src/lib/libcrypto/ec/ec_pmeth.c | 185 |
1 files changed, 89 insertions, 96 deletions
diff --git a/src/lib/libcrypto/ec/ec_pmeth.c b/src/lib/libcrypto/ec/ec_pmeth.c index c970d8c9ca..28f501070c 100644 --- a/src/lib/libcrypto/ec/ec_pmeth.c +++ b/src/lib/libcrypto/ec/ec_pmeth.c | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | * are met: | 9 | * are met: |
| 10 | * | 10 | * |
| 11 | * 1. Redistributions of source code must retain the above copyright | 11 | * 1. Redistributions of source code must retain the above copyright |
| 12 | * notice, this list of conditions and the following disclaimer. | 12 | * notice, this list of conditions and the following disclaimer. |
| 13 | * | 13 | * |
| 14 | * 2. Redistributions in binary form must reproduce the above copyright | 14 | * 2. Redistributions in binary form must reproduce the above copyright |
| 15 | * notice, this list of conditions and the following disclaimer in | 15 | * notice, this list of conditions and the following disclaimer in |
| @@ -66,16 +66,16 @@ | |||
| 66 | 66 | ||
| 67 | /* EC pkey context structure */ | 67 | /* EC pkey context structure */ |
| 68 | 68 | ||
| 69 | typedef struct | 69 | typedef struct { |
| 70 | { | ||
| 71 | /* Key and paramgen group */ | 70 | /* Key and paramgen group */ |
| 72 | EC_GROUP *gen_group; | 71 | EC_GROUP *gen_group; |
| 73 | /* message digest */ | 72 | /* message digest */ |
| 74 | const EVP_MD *md; | 73 | const EVP_MD *md; |
| 75 | } EC_PKEY_CTX; | 74 | } EC_PKEY_CTX; |
| 76 | 75 | ||
| 77 | static int pkey_ec_init(EVP_PKEY_CTX *ctx) | 76 | static int |
| 78 | { | 77 | pkey_ec_init(EVP_PKEY_CTX * ctx) |
| 78 | { | ||
| 79 | EC_PKEY_CTX *dctx; | 79 | EC_PKEY_CTX *dctx; |
| 80 | dctx = malloc(sizeof(EC_PKEY_CTX)); | 80 | dctx = malloc(sizeof(EC_PKEY_CTX)); |
| 81 | if (!dctx) | 81 | if (!dctx) |
| @@ -86,55 +86,52 @@ static int pkey_ec_init(EVP_PKEY_CTX *ctx) | |||
| 86 | ctx->data = dctx; | 86 | ctx->data = dctx; |
| 87 | 87 | ||
| 88 | return 1; | 88 | return 1; |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | static int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) | 91 | static int |
| 92 | { | 92 | pkey_ec_copy(EVP_PKEY_CTX * dst, EVP_PKEY_CTX * src) |
| 93 | { | ||
| 93 | EC_PKEY_CTX *dctx, *sctx; | 94 | EC_PKEY_CTX *dctx, *sctx; |
| 94 | if (!pkey_ec_init(dst)) | 95 | if (!pkey_ec_init(dst)) |
| 95 | return 0; | 96 | return 0; |
| 96 | sctx = src->data; | 97 | sctx = src->data; |
| 97 | dctx = dst->data; | 98 | dctx = dst->data; |
| 98 | if (sctx->gen_group) | 99 | if (sctx->gen_group) { |
| 99 | { | ||
| 100 | dctx->gen_group = EC_GROUP_dup(sctx->gen_group); | 100 | dctx->gen_group = EC_GROUP_dup(sctx->gen_group); |
| 101 | if (!dctx->gen_group) | 101 | if (!dctx->gen_group) |
| 102 | return 0; | 102 | return 0; |
| 103 | } | 103 | } |
| 104 | dctx->md = sctx->md; | 104 | dctx->md = sctx->md; |
| 105 | return 1; | 105 | return 1; |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx) | 108 | static void |
| 109 | { | 109 | pkey_ec_cleanup(EVP_PKEY_CTX * ctx) |
| 110 | { | ||
| 110 | EC_PKEY_CTX *dctx = ctx->data; | 111 | EC_PKEY_CTX *dctx = ctx->data; |
| 111 | if (dctx) | 112 | if (dctx) { |
| 112 | { | ||
| 113 | if (dctx->gen_group) | 113 | if (dctx->gen_group) |
| 114 | EC_GROUP_free(dctx->gen_group); | 114 | EC_GROUP_free(dctx->gen_group); |
| 115 | free(dctx); | 115 | free(dctx); |
| 116 | } | ||
| 117 | } | 116 | } |
| 117 | } | ||
| 118 | 118 | ||
| 119 | static int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, | 119 | static int |
| 120 | const unsigned char *tbs, size_t tbslen) | 120 | pkey_ec_sign(EVP_PKEY_CTX * ctx, unsigned char *sig, size_t * siglen, |
| 121 | { | 121 | const unsigned char *tbs, size_t tbslen) |
| 122 | { | ||
| 122 | int ret, type; | 123 | int ret, type; |
| 123 | unsigned int sltmp; | 124 | unsigned int sltmp; |
| 124 | EC_PKEY_CTX *dctx = ctx->data; | 125 | EC_PKEY_CTX *dctx = ctx->data; |
| 125 | EC_KEY *ec = ctx->pkey->pkey.ec; | 126 | EC_KEY *ec = ctx->pkey->pkey.ec; |
| 126 | 127 | ||
| 127 | if (!sig) | 128 | if (!sig) { |
| 128 | { | ||
| 129 | *siglen = ECDSA_size(ec); | 129 | *siglen = ECDSA_size(ec); |
| 130 | return 1; | 130 | return 1; |
| 131 | } | 131 | } else if (*siglen < (size_t) ECDSA_size(ec)) { |
| 132 | else if(*siglen < (size_t)ECDSA_size(ec)) | ||
| 133 | { | ||
| 134 | ECerr(EC_F_PKEY_EC_SIGN, EC_R_BUFFER_TOO_SMALL); | 132 | ECerr(EC_F_PKEY_EC_SIGN, EC_R_BUFFER_TOO_SMALL); |
| 135 | return 0; | 133 | return 0; |
| 136 | } | 134 | } |
| 137 | |||
| 138 | if (dctx->md) | 135 | if (dctx->md) |
| 139 | type = EVP_MD_type(dctx->md); | 136 | type = EVP_MD_type(dctx->md); |
| 140 | else | 137 | else |
| @@ -145,14 +142,15 @@ static int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, | |||
| 145 | 142 | ||
| 146 | if (ret <= 0) | 143 | if (ret <= 0) |
| 147 | return ret; | 144 | return ret; |
| 148 | *siglen = (size_t)sltmp; | 145 | *siglen = (size_t) sltmp; |
| 149 | return 1; | 146 | return 1; |
| 150 | } | 147 | } |
| 151 | 148 | ||
| 152 | static int pkey_ec_verify(EVP_PKEY_CTX *ctx, | 149 | static int |
| 153 | const unsigned char *sig, size_t siglen, | 150 | pkey_ec_verify(EVP_PKEY_CTX * ctx, |
| 154 | const unsigned char *tbs, size_t tbslen) | 151 | const unsigned char *sig, size_t siglen, |
| 155 | { | 152 | const unsigned char *tbs, size_t tbslen) |
| 153 | { | ||
| 156 | int ret, type; | 154 | int ret, type; |
| 157 | EC_PKEY_CTX *dctx = ctx->data; | 155 | EC_PKEY_CTX *dctx = ctx->data; |
| 158 | EC_KEY *ec = ctx->pkey->pkey.ec; | 156 | EC_KEY *ec = ctx->pkey->pkey.ec; |
| @@ -165,116 +163,111 @@ static int pkey_ec_verify(EVP_PKEY_CTX *ctx, | |||
| 165 | ret = ECDSA_verify(type, tbs, tbslen, sig, siglen, ec); | 163 | ret = ECDSA_verify(type, tbs, tbslen, sig, siglen, ec); |
| 166 | 164 | ||
| 167 | return ret; | 165 | return ret; |
| 168 | } | 166 | } |
| 169 | 167 | ||
| 170 | static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) | 168 | static int |
| 171 | { | 169 | pkey_ec_derive(EVP_PKEY_CTX * ctx, unsigned char *key, size_t * keylen) |
| 170 | { | ||
| 172 | int ret; | 171 | int ret; |
| 173 | size_t outlen; | 172 | size_t outlen; |
| 174 | const EC_POINT *pubkey = NULL; | 173 | const EC_POINT *pubkey = NULL; |
| 175 | if (!ctx->pkey || !ctx->peerkey) | 174 | if (!ctx->pkey || !ctx->peerkey) { |
| 176 | { | ||
| 177 | ECerr(EC_F_PKEY_EC_DERIVE, EC_R_KEYS_NOT_SET); | 175 | ECerr(EC_F_PKEY_EC_DERIVE, EC_R_KEYS_NOT_SET); |
| 178 | return 0; | 176 | return 0; |
| 179 | } | 177 | } |
| 180 | 178 | if (!key) { | |
| 181 | if (!key) | ||
| 182 | { | ||
| 183 | const EC_GROUP *group; | 179 | const EC_GROUP *group; |
| 184 | group = EC_KEY_get0_group(ctx->pkey->pkey.ec); | 180 | group = EC_KEY_get0_group(ctx->pkey->pkey.ec); |
| 185 | *keylen = (EC_GROUP_get_degree(group) + 7)/8; | 181 | *keylen = (EC_GROUP_get_degree(group) + 7) / 8; |
| 186 | return 1; | 182 | return 1; |
| 187 | } | 183 | } |
| 188 | |||
| 189 | pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec); | 184 | pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec); |
| 190 | 185 | ||
| 191 | /* NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is | 186 | /* |
| 187 | * NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is | ||
| 192 | * not an error, the result is truncated. | 188 | * not an error, the result is truncated. |
| 193 | */ | 189 | */ |
| 194 | 190 | ||
| 195 | outlen = *keylen; | 191 | outlen = *keylen; |
| 196 | 192 | ||
| 197 | ret = ECDH_compute_key(key, outlen, pubkey, ctx->pkey->pkey.ec, 0); | 193 | ret = ECDH_compute_key(key, outlen, pubkey, ctx->pkey->pkey.ec, 0); |
| 198 | if (ret < 0) | 194 | if (ret < 0) |
| 199 | return ret; | 195 | return ret; |
| 200 | *keylen = ret; | 196 | *keylen = ret; |
| 201 | return 1; | 197 | return 1; |
| 202 | } | 198 | } |
| 203 | 199 | ||
| 204 | static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) | 200 | static int |
| 205 | { | 201 | pkey_ec_ctrl(EVP_PKEY_CTX * ctx, int type, int p1, void *p2) |
| 202 | { | ||
| 206 | EC_PKEY_CTX *dctx = ctx->data; | 203 | EC_PKEY_CTX *dctx = ctx->data; |
| 207 | EC_GROUP *group; | 204 | EC_GROUP *group; |
| 208 | switch (type) | 205 | switch (type) { |
| 209 | { | 206 | case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: |
| 210 | case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: | ||
| 211 | group = EC_GROUP_new_by_curve_name(p1); | 207 | group = EC_GROUP_new_by_curve_name(p1); |
| 212 | if (group == NULL) | 208 | if (group == NULL) { |
| 213 | { | ||
| 214 | ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_CURVE); | 209 | ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_CURVE); |
| 215 | return 0; | 210 | return 0; |
| 216 | } | 211 | } |
| 217 | if (dctx->gen_group) | 212 | if (dctx->gen_group) |
| 218 | EC_GROUP_free(dctx->gen_group); | 213 | EC_GROUP_free(dctx->gen_group); |
| 219 | dctx->gen_group = group; | 214 | dctx->gen_group = group; |
| 220 | return 1; | 215 | return 1; |
| 221 | 216 | ||
| 222 | case EVP_PKEY_CTRL_MD: | 217 | case EVP_PKEY_CTRL_MD: |
| 223 | if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 && | 218 | if (EVP_MD_type((const EVP_MD *) p2) != NID_sha1 && |
| 224 | EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 && | 219 | EVP_MD_type((const EVP_MD *) p2) != NID_ecdsa_with_SHA1 && |
| 225 | EVP_MD_type((const EVP_MD *)p2) != NID_sha224 && | 220 | EVP_MD_type((const EVP_MD *) p2) != NID_sha224 && |
| 226 | EVP_MD_type((const EVP_MD *)p2) != NID_sha256 && | 221 | EVP_MD_type((const EVP_MD *) p2) != NID_sha256 && |
| 227 | EVP_MD_type((const EVP_MD *)p2) != NID_sha384 && | 222 | EVP_MD_type((const EVP_MD *) p2) != NID_sha384 && |
| 228 | EVP_MD_type((const EVP_MD *)p2) != NID_sha512) | 223 | EVP_MD_type((const EVP_MD *) p2) != NID_sha512) { |
| 229 | { | ||
| 230 | ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE); | 224 | ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE); |
| 231 | return 0; | 225 | return 0; |
| 232 | } | 226 | } |
| 233 | dctx->md = p2; | 227 | dctx->md = p2; |
| 234 | return 1; | 228 | return 1; |
| 235 | 229 | ||
| 236 | case EVP_PKEY_CTRL_PEER_KEY: | 230 | case EVP_PKEY_CTRL_PEER_KEY: |
| 237 | /* Default behaviour is OK */ | 231 | /* Default behaviour is OK */ |
| 238 | case EVP_PKEY_CTRL_DIGESTINIT: | 232 | case EVP_PKEY_CTRL_DIGESTINIT: |
| 239 | case EVP_PKEY_CTRL_PKCS7_SIGN: | 233 | case EVP_PKEY_CTRL_PKCS7_SIGN: |
| 240 | case EVP_PKEY_CTRL_CMS_SIGN: | 234 | case EVP_PKEY_CTRL_CMS_SIGN: |
| 241 | return 1; | 235 | return 1; |
| 242 | 236 | ||
| 243 | default: | 237 | default: |
| 244 | return -2; | 238 | return -2; |
| 245 | 239 | ||
| 246 | } | ||
| 247 | } | 240 | } |
| 248 | 241 | } | |
| 249 | static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx, | 242 | |
| 250 | const char *type, const char *value) | 243 | static int |
| 251 | { | 244 | pkey_ec_ctrl_str(EVP_PKEY_CTX * ctx, |
| 252 | if (!strcmp(type, "ec_paramgen_curve")) | 245 | const char *type, const char *value) |
| 253 | { | 246 | { |
| 247 | if (!strcmp(type, "ec_paramgen_curve")) { | ||
| 254 | int nid; | 248 | int nid; |
| 255 | nid = OBJ_sn2nid(value); | 249 | nid = OBJ_sn2nid(value); |
| 256 | if (nid == NID_undef) | 250 | if (nid == NID_undef) |
| 257 | nid = OBJ_ln2nid(value); | 251 | nid = OBJ_ln2nid(value); |
| 258 | if (nid == NID_undef) | 252 | if (nid == NID_undef) { |
| 259 | { | ||
| 260 | ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_CURVE); | 253 | ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_CURVE); |
| 261 | return 0; | 254 | return 0; |
| 262 | } | ||
| 263 | return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); | ||
| 264 | } | 255 | } |
| 265 | return -2; | 256 | return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); |
| 266 | } | 257 | } |
| 258 | return -2; | ||
| 259 | } | ||
| 267 | 260 | ||
| 268 | static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) | 261 | static int |
| 269 | { | 262 | pkey_ec_paramgen(EVP_PKEY_CTX * ctx, EVP_PKEY * pkey) |
| 263 | { | ||
| 270 | EC_KEY *ec = NULL; | 264 | EC_KEY *ec = NULL; |
| 271 | EC_PKEY_CTX *dctx = ctx->data; | 265 | EC_PKEY_CTX *dctx = ctx->data; |
| 272 | int ret = 0; | 266 | int ret = 0; |
| 273 | if (dctx->gen_group == NULL) | 267 | if (dctx->gen_group == NULL) { |
| 274 | { | ||
| 275 | ECerr(EC_F_PKEY_EC_PARAMGEN, EC_R_NO_PARAMETERS_SET); | 268 | ECerr(EC_F_PKEY_EC_PARAMGEN, EC_R_NO_PARAMETERS_SET); |
| 276 | return 0; | 269 | return 0; |
| 277 | } | 270 | } |
| 278 | ec = EC_KEY_new(); | 271 | ec = EC_KEY_new(); |
| 279 | if (!ec) | 272 | if (!ec) |
| 280 | return 0; | 273 | return 0; |
| @@ -284,16 +277,16 @@ static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) | |||
| 284 | else | 277 | else |
| 285 | EC_KEY_free(ec); | 278 | EC_KEY_free(ec); |
| 286 | return ret; | 279 | return ret; |
| 287 | } | 280 | } |
| 288 | 281 | ||
| 289 | static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) | 282 | static int |
| 290 | { | 283 | pkey_ec_keygen(EVP_PKEY_CTX * ctx, EVP_PKEY * pkey) |
| 284 | { | ||
| 291 | EC_KEY *ec = NULL; | 285 | EC_KEY *ec = NULL; |
| 292 | if (ctx->pkey == NULL) | 286 | if (ctx->pkey == NULL) { |
| 293 | { | ||
| 294 | ECerr(EC_F_PKEY_EC_KEYGEN, EC_R_NO_PARAMETERS_SET); | 287 | ECerr(EC_F_PKEY_EC_KEYGEN, EC_R_NO_PARAMETERS_SET); |
| 295 | return 0; | 288 | return 0; |
| 296 | } | 289 | } |
| 297 | ec = EC_KEY_new(); | 290 | ec = EC_KEY_new(); |
| 298 | if (!ec) | 291 | if (!ec) |
| 299 | return 0; | 292 | return 0; |
| @@ -302,7 +295,7 @@ static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) | |||
| 302 | if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) | 295 | if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) |
| 303 | return 0; | 296 | return 0; |
| 304 | return EC_KEY_generate_key(pkey->pkey.ec); | 297 | return EC_KEY_generate_key(pkey->pkey.ec); |
| 305 | } | 298 | } |
| 306 | 299 | ||
| 307 | const EVP_PKEY_METHOD ec_pkey_meth = { | 300 | const EVP_PKEY_METHOD ec_pkey_meth = { |
| 308 | .pkey_id = EVP_PKEY_EC, | 301 | .pkey_id = EVP_PKEY_EC, |
