]>
Commit | Line | Data |
---|---|---|
4f22f405 | 1 | /* |
8020d79b | 2 | * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved. |
aa8f3d76 | 3 | * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved |
4f22f405 | 4 | * |
a7f182b7 | 5 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
4f22f405 RS |
6 | * this file except in compliance with the License. You can obtain a copy |
7 | * in the file LICENSE in the source distribution or at | |
8 | * https://www.openssl.org/source/license.html | |
9 | */ | |
10 | ||
579422c8 P |
11 | /* |
12 | * ECDH low level APIs are deprecated for public use, but still ok for | |
13 | * internal use. | |
14 | */ | |
15 | #include "internal/deprecated.h" | |
16 | ||
8b5bcef7 | 17 | #include <string.h> |
176f31dd BM |
18 | #include <limits.h> |
19 | ||
b39fc560 | 20 | #include "internal/cryptlib.h" |
10a66ad3 | 21 | |
e172d60d | 22 | #include <openssl/err.h> |
0f814687 | 23 | #include <openssl/bn.h> |
647b2238 DSH |
24 | #include <openssl/objects.h> |
25 | #include <openssl/ec.h> | |
706457b7 | 26 | #include "ec_local.h" |
e172d60d | 27 | |
e2285d87 DSH |
28 | int ossl_ecdh_compute_key(unsigned char **psec, size_t *pseclen, |
29 | const EC_POINT *pub_key, const EC_KEY *ecdh) | |
77470e98 | 30 | { |
9ff9bccc | 31 | if (ecdh->group->meth->ecdh_compute_key == NULL) { |
9311d0c4 | 32 | ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_ECDH); |
65ea288d | 33 | return 0; |
77470e98 DSH |
34 | } |
35 | ||
e2285d87 | 36 | return ecdh->group->meth->ecdh_compute_key(psec, pseclen, pub_key, ecdh); |
77470e98 DSH |
37 | } |
38 | ||
3a83462d | 39 | /*- |
f1004830 SL |
40 | * This implementation is based on the following primitives in the |
41 | * IEEE 1363 standard: | |
e172d60d BM |
42 | * - ECKAS-DH1 |
43 | * - ECSVDP-DH | |
f1004830 SL |
44 | * |
45 | * It also conforms to SP800-56A r3 | |
46 | * See Section 5.7.1.2 "Elliptic Curve Cryptography Cofactor Diffie-Hellman | |
47 | * (ECC CDH) Primitive:". The steps listed below refer to SP800-56A. | |
e172d60d | 48 | */ |
32ab57cb SL |
49 | int ossl_ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen, |
50 | const EC_POINT *pub_key, const EC_KEY *ecdh) | |
0f113f3e MC |
51 | { |
52 | BN_CTX *ctx; | |
53 | EC_POINT *tmp = NULL; | |
ddc1caac | 54 | BIGNUM *x = NULL; |
0f113f3e MC |
55 | const BIGNUM *priv_key; |
56 | const EC_GROUP *group; | |
e2285d87 | 57 | int ret = 0; |
0f113f3e MC |
58 | size_t buflen, len; |
59 | unsigned char *buf = NULL; | |
60 | ||
a9612d6c | 61 | if ((ctx = BN_CTX_new_ex(ecdh->libctx)) == NULL) |
0f113f3e MC |
62 | goto err; |
63 | BN_CTX_start(ctx); | |
64 | x = BN_CTX_get(ctx); | |
ddc1caac | 65 | if (x == NULL) { |
e077455e | 66 | ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); |
abea494c BE |
67 | goto err; |
68 | } | |
0f113f3e MC |
69 | |
70 | priv_key = EC_KEY_get0_private_key(ecdh); | |
71 | if (priv_key == NULL) { | |
9311d0c4 | 72 | ERR_raise(ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY); |
0f113f3e MC |
73 | goto err; |
74 | } | |
75 | ||
76 | group = EC_KEY_get0_group(ecdh); | |
77 | ||
f1004830 SL |
78 | /* |
79 | * Step(1) - Compute the point tmp = cofactor * owners_private_key | |
80 | * * peer_public_key. | |
81 | */ | |
0f113f3e | 82 | if (EC_KEY_get_flags(ecdh) & EC_FLAG_COFACTOR_ECDH) { |
e077455e RL |
83 | if (!EC_GROUP_get_cofactor(group, x, NULL)) { |
84 | ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); | |
85 | goto err; | |
86 | } | |
87 | if (!BN_mul(x, x, priv_key, ctx)) { | |
88 | ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); | |
0f113f3e MC |
89 | goto err; |
90 | } | |
91 | priv_key = x; | |
92 | } | |
93 | ||
94 | if ((tmp = EC_POINT_new(group)) == NULL) { | |
e077455e | 95 | ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); |
0f113f3e MC |
96 | goto err; |
97 | } | |
98 | ||
99 | if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx)) { | |
9311d0c4 | 100 | ERR_raise(ERR_LIB_EC, EC_R_POINT_ARITHMETIC_FAILURE); |
0f113f3e MC |
101 | goto err; |
102 | } | |
103 | ||
f1004830 SL |
104 | /* |
105 | * Step(2) : If point tmp is at infinity then clear intermediate values and | |
106 | * exit. Note: getting affine coordinates returns 0 if point is at infinity. | |
107 | * Step(3a) : Get x-coordinate of point x = tmp.x | |
108 | */ | |
9cc570d4 | 109 | if (!EC_POINT_get_affine_coordinates(group, tmp, x, NULL, ctx)) { |
9311d0c4 | 110 | ERR_raise(ERR_LIB_EC, EC_R_POINT_ARITHMETIC_FAILURE); |
9cc570d4 | 111 | goto err; |
0f113f3e | 112 | } |
e172d60d | 113 | |
f1004830 SL |
114 | /* |
115 | * Step(3b) : convert x to a byte string, using the field-element-to-byte | |
116 | * string conversion routine defined in Appendix C.2 | |
117 | */ | |
0f113f3e MC |
118 | buflen = (EC_GROUP_get_degree(group) + 7) / 8; |
119 | len = BN_num_bytes(x); | |
120 | if (len > buflen) { | |
9311d0c4 | 121 | ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); |
0f113f3e MC |
122 | goto err; |
123 | } | |
e077455e | 124 | if ((buf = OPENSSL_malloc(buflen)) == NULL) |
0f113f3e | 125 | goto err; |
0f113f3e MC |
126 | |
127 | memset(buf, 0, buflen - len); | |
128 | if (len != (size_t)BN_bn2bin(x, buf + buflen - len)) { | |
9311d0c4 | 129 | ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); |
0f113f3e MC |
130 | goto err; |
131 | } | |
132 | ||
e2285d87 DSH |
133 | *pout = buf; |
134 | *poutlen = buflen; | |
135 | buf = NULL; | |
136 | ||
137 | ret = 1; | |
0f113f3e MC |
138 | |
139 | err: | |
f1004830 SL |
140 | /* Step(4) : Destroy all intermediate calculations */ |
141 | BN_clear(x); | |
1ff2c992 | 142 | EC_POINT_clear_free(tmp); |
ce1415ed | 143 | BN_CTX_end(ctx); |
23a1d5e9 | 144 | BN_CTX_free(ctx); |
b548a1f1 | 145 | OPENSSL_free(buf); |
e2285d87 | 146 | return ret; |
0f113f3e | 147 | } |