Branch data Line data Source code
1 : : /* crypto/ecdh/ech_ossl.c */
2 : : /* ====================================================================
3 : : * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
4 : : *
5 : : * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
6 : : * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
7 : : * to the OpenSSL project.
8 : : *
9 : : * The ECC Code is licensed pursuant to the OpenSSL open source
10 : : * license provided below.
11 : : *
12 : : * The ECDH software is originally written by Douglas Stebila of
13 : : * Sun Microsystems Laboratories.
14 : : *
15 : : */
16 : : /* ====================================================================
17 : : * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
18 : : *
19 : : * Redistribution and use in source and binary forms, with or without
20 : : * modification, are permitted provided that the following conditions
21 : : * are met:
22 : : *
23 : : * 1. Redistributions of source code must retain the above copyright
24 : : * notice, this list of conditions and the following disclaimer.
25 : : *
26 : : * 2. Redistributions in binary form must reproduce the above copyright
27 : : * notice, this list of conditions and the following disclaimer in
28 : : * the documentation and/or other materials provided with the
29 : : * distribution.
30 : : *
31 : : * 3. All advertising materials mentioning features or use of this
32 : : * software must display the following acknowledgment:
33 : : * "This product includes software developed by the OpenSSL Project
34 : : * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
35 : : *
36 : : * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
37 : : * endorse or promote products derived from this software without
38 : : * prior written permission. For written permission, please contact
39 : : * openssl-core@OpenSSL.org.
40 : : *
41 : : * 5. Products derived from this software may not be called "OpenSSL"
42 : : * nor may "OpenSSL" appear in their names without prior written
43 : : * permission of the OpenSSL Project.
44 : : *
45 : : * 6. Redistributions of any form whatsoever must retain the following
46 : : * acknowledgment:
47 : : * "This product includes software developed by the OpenSSL Project
48 : : * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
49 : : *
50 : : * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
51 : : * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 : : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53 : : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
54 : : * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 : : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
56 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57 : : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 : : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
59 : : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60 : : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
61 : : * OF THE POSSIBILITY OF SUCH DAMAGE.
62 : : * ====================================================================
63 : : *
64 : : * This product includes cryptographic software written by Eric Young
65 : : * (eay@cryptsoft.com). This product includes software written by Tim
66 : : * Hudson (tjh@cryptsoft.com).
67 : : *
68 : : */
69 : :
70 : : #define OPENSSL_FIPSAPI
71 : :
72 : : #include <string.h>
73 : : #include <limits.h>
74 : :
75 : : #include "cryptlib.h"
76 : :
77 : : #include "ech_locl.h"
78 : : #include <openssl/err.h>
79 : : #include <openssl/sha.h>
80 : : #include <openssl/obj_mac.h>
81 : : #include <openssl/bn.h>
82 : :
83 : : static int ecdh_compute_key(void *out, size_t len, const EC_POINT *pub_key,
84 : : EC_KEY *ecdh,
85 : : void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen));
86 : :
87 : : static ECDH_METHOD openssl_ecdh_meth = {
88 : : "OpenSSL ECDH method",
89 : : ecdh_compute_key,
90 : : #if 0
91 : : NULL, /* init */
92 : : NULL, /* finish */
93 : : #endif
94 : : ECDH_FLAG_FIPS_METHOD, /* flags */
95 : : NULL /* app_data */
96 : : };
97 : :
98 : 359 : const ECDH_METHOD *ECDH_OpenSSL(void)
99 : : {
100 : 359 : return &openssl_ecdh_meth;
101 : : }
102 : :
103 : :
104 : : /* This implementation is based on the following primitives in the IEEE 1363 standard:
105 : : * - ECKAS-DH1
106 : : * - ECSVDP-DH
107 : : * Finally an optional KDF is applied.
108 : : */
109 : 966 : static int ecdh_compute_key(void *out, size_t outlen, const EC_POINT *pub_key,
110 : : EC_KEY *ecdh,
111 : : void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen))
112 : : {
113 : : BN_CTX *ctx;
114 : 966 : EC_POINT *tmp=NULL;
115 : 966 : BIGNUM *x=NULL, *y=NULL;
116 : : const BIGNUM *priv_key;
117 : : const EC_GROUP* group;
118 : 966 : int ret= -1;
119 : : size_t buflen, len;
120 : 966 : unsigned char *buf=NULL;
121 : :
122 : : #ifdef OPENSSL_FIPS
123 : : if(FIPS_selftest_failed())
124 : : {
125 : : FIPSerr(FIPS_F_ECDH_COMPUTE_KEY,FIPS_R_FIPS_SELFTEST_FAILED);
126 : : return -1;
127 : : }
128 : : #endif
129 : :
130 [ - + ]: 966 : if (outlen > INT_MAX)
131 : : {
132 : 0 : ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE); /* sort of, anyway */
133 : 0 : return -1;
134 : : }
135 : :
136 [ + - ]: 966 : if ((ctx = BN_CTX_new()) == NULL) goto err;
137 : 966 : BN_CTX_start(ctx);
138 : 966 : x = BN_CTX_get(ctx);
139 : 966 : y = BN_CTX_get(ctx);
140 : :
141 : 966 : priv_key = EC_KEY_get0_private_key(ecdh);
142 [ - + ]: 966 : if (priv_key == NULL)
143 : : {
144 : 0 : ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_NO_PRIVATE_VALUE);
145 : 0 : goto err;
146 : : }
147 : :
148 : 966 : group = EC_KEY_get0_group(ecdh);
149 : :
150 [ + + ]: 966 : if (EC_KEY_get_flags(ecdh) & EC_FLAG_COFACTOR_ECDH)
151 : : {
152 [ + - - + ]: 4 : if (!EC_GROUP_get_cofactor(group, x, ctx) ||
153 : 2 : !BN_mul(x, x, priv_key, ctx))
154 : : {
155 : 0 : ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
156 : 0 : goto err;
157 : : }
158 : : priv_key = x;
159 : : }
160 : :
161 [ - + ]: 966 : if ((tmp=EC_POINT_new(group)) == NULL)
162 : : {
163 : 0 : ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE);
164 : 0 : goto err;
165 : : }
166 : :
167 [ - + ]: 966 : if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx))
168 : : {
169 : 0 : ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE);
170 : 0 : goto err;
171 : : }
172 : :
173 [ + + ]: 966 : if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field)
174 : : {
175 [ - + ]: 20 : if (!EC_POINT_get_affine_coordinates_GFp(group, tmp, x, y, ctx))
176 : : {
177 : 0 : ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE);
178 : 0 : goto err;
179 : : }
180 : : }
181 : : #ifndef OPENSSL_NO_EC2M
182 : : else
183 : : {
184 [ - + ]: 946 : if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp, x, y, ctx))
185 : : {
186 : 0 : ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE);
187 : 0 : goto err;
188 : : }
189 : : }
190 : : #endif
191 : :
192 : 966 : buflen = (EC_GROUP_get_degree(group) + 7)/8;
193 : 966 : len = BN_num_bytes(x);
194 [ - + ]: 966 : if (len > buflen)
195 : : {
196 : 0 : ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_INTERNAL_ERROR);
197 : 0 : goto err;
198 : : }
199 [ - + ]: 966 : if ((buf = OPENSSL_malloc(buflen)) == NULL)
200 : : {
201 : 0 : ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE);
202 : 0 : goto err;
203 : : }
204 : :
205 : 966 : memset(buf, 0, buflen - len);
206 [ - + ]: 966 : if (len != (size_t)BN_bn2bin(x, buf + buflen - len))
207 : : {
208 : 0 : ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_BN_LIB);
209 : 0 : goto err;
210 : : }
211 : :
212 [ + + ]: 966 : if (KDF != 0)
213 : : {
214 [ - + ]: 30 : if (KDF(buf, buflen, out, &outlen) == NULL)
215 : : {
216 : 0 : ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_KDF_FAILED);
217 : 0 : goto err;
218 : : }
219 : 30 : ret = outlen;
220 : : }
221 : : else
222 : : {
223 : : /* no KDF, just copy as much as we can */
224 [ - + ]: 936 : if (outlen > buflen)
225 : 0 : outlen = buflen;
226 : 936 : memcpy(out, buf, outlen);
227 : 936 : ret = outlen;
228 : : }
229 : :
230 : : err:
231 [ + - ]: 966 : if (tmp) EC_POINT_free(tmp);
232 [ + - ]: 966 : if (ctx) BN_CTX_end(ctx);
233 [ + - ]: 966 : if (ctx) BN_CTX_free(ctx);
234 [ + - ]: 966 : if (buf) OPENSSL_free(buf);
235 : 966 : return(ret);
236 : : }
237 : :
238 : : #ifdef OPENSSL_FIPSCANISTER
239 : : /* FIPS stanadlone version of ecdh_check: just return FIPS method */
240 : : ECDH_DATA *fips_ecdh_check(EC_KEY *key)
241 : : {
242 : : static ECDH_DATA rv = {
243 : : 0,0,0,
244 : : &openssl_ecdh_meth
245 : : };
246 : : return &rv;
247 : : }
248 : : #endif
|