]>
Commit | Line | Data |
---|---|---|
440e5d80 RS |
1 | /* |
2 | * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. | |
3 | * | |
4 | * Licensed under the OpenSSL license (the "License"). You may not use | |
5 | * this file except in compliance with the License. You can obtain a copy | |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
8 | */ | |
9 | ||
e172d60d BM |
10 | /* ==================================================================== |
11 | * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. | |
12 | * | |
13 | * The Elliptic Curve Public-Key Crypto Library (ECC Code) included | |
14 | * herein is developed by SUN MICROSYSTEMS, INC., and is contributed | |
15 | * to the OpenSSL project. | |
16 | * | |
17 | * The ECC Code is licensed pursuant to the OpenSSL open source | |
18 | * license provided below. | |
19 | * | |
e172d60d BM |
20 | * The ECDH software is originally written by Douglas Stebila of |
21 | * Sun Microsystems Laboratories. | |
22 | * | |
23 | */ | |
e172d60d BM |
24 | |
25 | #include <stdio.h> | |
26 | #include <stdlib.h> | |
27 | #include <string.h> | |
55f78baf RL |
28 | |
29 | #include "../e_os.h" | |
30 | ||
10bf4fc2 | 31 | #include <openssl/opensslconf.h> /* for OPENSSL_NO_EC */ |
e172d60d BM |
32 | #include <openssl/crypto.h> |
33 | #include <openssl/bio.h> | |
34 | #include <openssl/bn.h> | |
e172d60d BM |
35 | #include <openssl/objects.h> |
36 | #include <openssl/rand.h> | |
176f31dd | 37 | #include <openssl/sha.h> |
e172d60d BM |
38 | #include <openssl/err.h> |
39 | ||
10bf4fc2 | 40 | #ifdef OPENSSL_NO_EC |
e172d60d BM |
41 | int main(int argc, char *argv[]) |
42 | { | |
43 | printf("No ECDH support\n"); | |
0f113f3e | 44 | return (0); |
e172d60d BM |
45 | } |
46 | #else | |
0f113f3e | 47 | # include <openssl/ec.h> |
e172d60d | 48 | |
0f113f3e MC |
49 | static const char rnd_seed[] = |
50 | "string to make the random number generator think it has entropy"; | |
176f31dd | 51 | |
da317b94 DSH |
52 | /* Given private value and NID, create EC_KEY structure */ |
53 | ||
b438f0ed | 54 | static EC_KEY *mk_eckey(int nid, const char *str) |
0f113f3e MC |
55 | { |
56 | int ok = 0; | |
57 | EC_KEY *k = NULL; | |
58 | BIGNUM *priv = NULL; | |
59 | EC_POINT *pub = NULL; | |
60 | const EC_GROUP *grp; | |
61 | k = EC_KEY_new_by_curve_name(nid); | |
62 | if (!k) | |
63 | goto err; | |
b438f0ed BB |
64 | if(!BN_hex2bn(&priv, str)) |
65 | goto err; | |
0f113f3e MC |
66 | if (!priv) |
67 | goto err; | |
68 | if (!EC_KEY_set_private_key(k, priv)) | |
69 | goto err; | |
70 | grp = EC_KEY_get0_group(k); | |
71 | pub = EC_POINT_new(grp); | |
72 | if (!pub) | |
73 | goto err; | |
74 | if (!EC_POINT_mul(grp, pub, priv, NULL, NULL, NULL)) | |
75 | goto err; | |
76 | if (!EC_KEY_set_public_key(k, pub)) | |
77 | goto err; | |
78 | ok = 1; | |
79 | err: | |
23a1d5e9 | 80 | BN_clear_free(priv); |
8fdc3734 | 81 | EC_POINT_free(pub); |
0f113f3e MC |
82 | if (ok) |
83 | return k; | |
8fdc3734 | 84 | EC_KEY_free(k); |
0f113f3e MC |
85 | return NULL; |
86 | } | |
87 | ||
61f6774e BB |
88 | #include "ecdhtest_cavs.h" |
89 | ||
0543603a BB |
90 | /* |
91 | * NIST SP800-56A co-factor ECDH tests. | |
92 | * KATs taken from NIST documents with parameters: | |
93 | * | |
94 | * - (QCAVSx,QCAVSy) is the public key for CAVS. | |
95 | * - dIUT is the private key for IUT. | |
96 | * - (QIUTx,QIUTy) is the public key for IUT. | |
97 | * - ZIUT is the shared secret KAT. | |
98 | * | |
99 | * CAVS: Cryptographic Algorithm Validation System | |
100 | * IUT: Implementation Under Test | |
101 | * | |
102 | * This function tests two things: | |
103 | * | |
104 | * 1. dIUT * G = (QIUTx,QIUTy) | |
105 | * i.e. public key for IUT computes correctly. | |
106 | * 2. x-coord of cofactor * dIUT * (QCAVSx,QCAVSy) = ZIUT | |
107 | * i.e. co-factor ECDH key computes correctly. | |
108 | * | |
109 | * returns zero on failure or unsupported curve. One otherwise. | |
110 | */ | |
61f6774e BB |
111 | static int ecdh_cavs_kat(BIO *out, const ecdh_cavs_kat_t *kat) |
112 | { | |
113 | int rv = 0, is_char_two = 0; | |
114 | EC_KEY *key1 = NULL; | |
115 | EC_POINT *pub = NULL; | |
116 | const EC_GROUP *group = NULL; | |
117 | BIGNUM *bnz = NULL, *x = NULL, *y = NULL; | |
118 | unsigned char *Ztmp = NULL, *Z = NULL; | |
119 | size_t Ztmplen, Zlen; | |
120 | BIO_puts(out, "Testing ECC CDH Primitive SP800-56A with "); | |
121 | BIO_puts(out, OBJ_nid2sn(kat->nid)); | |
122 | ||
123 | /* dIUT is IUT's private key */ | |
124 | if ((key1 = mk_eckey(kat->nid, kat->dIUT)) == NULL) | |
125 | goto err; | |
126 | /* these are cofactor ECDH KATs */ | |
127 | EC_KEY_set_flags(key1, EC_FLAG_COFACTOR_ECDH); | |
128 | ||
129 | if ((group = EC_KEY_get0_group(key1)) == NULL) | |
130 | goto err; | |
131 | if ((pub = EC_POINT_new(group)) == NULL) | |
132 | goto err; | |
133 | ||
134 | if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_characteristic_two_field) | |
135 | is_char_two = 1; | |
136 | ||
137 | /* (QIUTx, QIUTy) is IUT's public key */ | |
138 | if(!BN_hex2bn(&x, kat->QIUTx)) | |
139 | goto err; | |
140 | if(!BN_hex2bn(&y, kat->QIUTy)) | |
141 | goto err; | |
142 | if (is_char_two) { | |
0543603a BB |
143 | #ifdef OPENSSL_NO_EC2M |
144 | goto err; | |
145 | #else | |
61f6774e | 146 | if (!EC_POINT_set_affine_coordinates_GF2m(group, pub, x, y, NULL)) |
61f6774e | 147 | goto err; |
a67788c1 | 148 | #endif |
61f6774e BB |
149 | } |
150 | else { | |
151 | if (!EC_POINT_set_affine_coordinates_GFp(group, pub, x, y, NULL)) | |
152 | goto err; | |
153 | } | |
154 | /* dIUT * G = (QIUTx, QIUTy) should hold */ | |
155 | if (EC_POINT_cmp(group, EC_KEY_get0_public_key(key1), pub, NULL)) | |
156 | goto err; | |
157 | ||
158 | /* (QCAVSx, QCAVSy) is CAVS's public key */ | |
159 | if(!BN_hex2bn(&x, kat->QCAVSx)) | |
160 | goto err; | |
161 | if(!BN_hex2bn(&y, kat->QCAVSy)) | |
162 | goto err; | |
163 | if (is_char_two) { | |
0543603a BB |
164 | #ifdef OPENSSL_NO_EC2M |
165 | goto err; | |
166 | #else | |
61f6774e | 167 | if (!EC_POINT_set_affine_coordinates_GF2m(group, pub, x, y, NULL)) |
61f6774e | 168 | goto err; |
a67788c1 | 169 | #endif |
61f6774e BB |
170 | } |
171 | else { | |
172 | if (!EC_POINT_set_affine_coordinates_GFp(group, pub, x, y, NULL)) | |
173 | goto err; | |
174 | } | |
175 | ||
176 | /* ZIUT is the shared secret */ | |
177 | if(!BN_hex2bn(&bnz, kat->ZIUT)) | |
178 | goto err; | |
179 | Ztmplen = (EC_GROUP_get_degree(EC_KEY_get0_group(key1)) + 7) / 8; | |
180 | Zlen = BN_num_bytes(bnz); | |
181 | if (Zlen > Ztmplen) | |
182 | goto err; | |
183 | if((Ztmp = OPENSSL_zalloc(Ztmplen)) == NULL) | |
184 | goto err; | |
185 | if((Z = OPENSSL_zalloc(Ztmplen)) == NULL) | |
186 | goto err; | |
187 | if(!BN_bn2binpad(bnz, Z, Ztmplen)) | |
188 | goto err; | |
189 | if (!ECDH_compute_key(Ztmp, Ztmplen, pub, key1, 0)) | |
190 | goto err; | |
191 | /* shared secrets should be identical */ | |
192 | if (memcmp(Ztmp, Z, Ztmplen)) | |
193 | goto err; | |
194 | rv = 1; | |
195 | err: | |
196 | EC_KEY_free(key1); | |
197 | EC_POINT_free(pub); | |
198 | BN_free(bnz); | |
199 | BN_free(x); | |
200 | BN_free(y); | |
201 | OPENSSL_free(Ztmp); | |
202 | OPENSSL_free(Z); | |
0543603a | 203 | if (rv) { |
61f6774e | 204 | BIO_puts(out, " ok\n"); |
0543603a | 205 | } |
61f6774e BB |
206 | else { |
207 | fprintf(stderr, "Error in ECC CDH routines\n"); | |
208 | ERR_print_errors_fp(stderr); | |
209 | } | |
210 | return rv; | |
211 | } | |
212 | ||
0f113f3e MC |
213 | int main(int argc, char *argv[]) |
214 | { | |
5c64c1bf | 215 | int ret = 1; |
e80a0f65 | 216 | size_t n = 0; |
0f113f3e MC |
217 | BIO *out; |
218 | ||
bbd86bf5 | 219 | CRYPTO_set_mem_debug(1); |
0f113f3e MC |
220 | CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); |
221 | ||
0f113f3e MC |
222 | RAND_seed(rnd_seed, sizeof rnd_seed); |
223 | ||
224 | out = BIO_new(BIO_s_file()); | |
225 | if (out == NULL) | |
226 | EXIT(1); | |
0f81f5f7 | 227 | BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT); |
0f113f3e | 228 | |
d663c2db | 229 | /* NAMED CURVES TESTS: moved to evptests.txt */ |
b438f0ed | 230 | |
29cbf152 | 231 | /* KATs: moved to evptests.txt */ |
0f113f3e | 232 | |
61f6774e BB |
233 | /* NIST SP800-56A co-factor ECDH KATs */ |
234 | for (n = 0; n < (sizeof(ecdh_cavs_kats)/sizeof(ecdh_cavs_kat_t)); n++) { | |
235 | if (!ecdh_cavs_kat(out, &ecdh_cavs_kats[n])) | |
236 | goto err; | |
237 | } | |
238 | ||
0f113f3e MC |
239 | ret = 0; |
240 | ||
241 | err: | |
242 | ERR_print_errors_fp(stderr); | |
0f113f3e | 243 | BIO_free(out); |
8793f012 | 244 | |
c2e27310 | 245 | #ifndef OPENSSL_NO_CRYPTO_MDEBUG |
541e9565 DSH |
246 | if (CRYPTO_mem_leaks_fp(stderr) <= 0) |
247 | ret = 1; | |
bbd86bf5 | 248 | #endif |
0f113f3e | 249 | EXIT(ret); |
0f113f3e | 250 | } |
c787525a | 251 | #endif |