source: EcnlProtoTool/trunk/openssl-1.1.0e/crypto/ec/ecx_meth.c@ 331

Last change on this file since 331 was 331, checked in by coas-nagasima, 6 years ago

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 9.3 KB
Line 
1/*
2 * Copyright 2006-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
10#include <stdio.h>
11#include "internal/cryptlib.h"
12#include <openssl/x509.h>
13#include <openssl/ec.h>
14#include <openssl/rand.h>
15#include "internal/asn1_int.h"
16#include "internal/evp_int.h"
17#include "ec_lcl.h"
18
19#define X25519_KEYLEN 32
20#define X25519_BITS 253
21#define X25519_SECURITY_BITS 128
22
23typedef struct {
24 unsigned char pubkey[X25519_KEYLEN];
25 unsigned char *privkey;
26} X25519_KEY;
27
28typedef enum {
29 X25519_PUBLIC,
30 X25519_PRIVATE,
31 X25519_KEYGEN
32} ecx_key_op_t;
33
34/* Setup EVP_PKEY using public, private or generation */
35static int ecx_key_op(EVP_PKEY *pkey, const X509_ALGOR *palg,
36 const unsigned char *p, int plen, ecx_key_op_t op)
37{
38 X25519_KEY *xkey;
39
40 if (op != X25519_KEYGEN) {
41 if (palg != NULL) {
42 int ptype;
43
44 /* Algorithm parameters must be absent */
45 X509_ALGOR_get0(NULL, &ptype, NULL, palg);
46 if (ptype != V_ASN1_UNDEF) {
47 ECerr(EC_F_ECX_KEY_OP, EC_R_INVALID_ENCODING);
48 return 0;
49 }
50 }
51
52 if (p == NULL || plen != X25519_KEYLEN) {
53 ECerr(EC_F_ECX_KEY_OP, EC_R_INVALID_ENCODING);
54 return 0;
55 }
56 }
57
58 xkey = OPENSSL_zalloc(sizeof(*xkey));
59 if (xkey == NULL) {
60 ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE);
61 return 0;
62 }
63
64 if (op == X25519_PUBLIC) {
65 memcpy(xkey->pubkey, p, plen);
66 } else {
67 xkey->privkey = OPENSSL_secure_malloc(X25519_KEYLEN);
68 if (xkey->privkey == NULL) {
69 ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE);
70 OPENSSL_free(xkey);
71 return 0;
72 }
73 if (op == X25519_KEYGEN) {
74 if (RAND_bytes(xkey->privkey, X25519_KEYLEN) <= 0) {
75 OPENSSL_secure_free(xkey->privkey);
76 OPENSSL_free(xkey);
77 return 0;
78 }
79 xkey->privkey[0] &= 248;
80 xkey->privkey[31] &= 127;
81 xkey->privkey[31] |= 64;
82 } else {
83 memcpy(xkey->privkey, p, X25519_KEYLEN);
84 }
85 X25519_public_from_private(xkey->pubkey, xkey->privkey);
86 }
87
88 EVP_PKEY_assign(pkey, NID_X25519, xkey);
89 return 1;
90}
91
92static int ecx_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
93{
94 const X25519_KEY *xkey = pkey->pkey.ptr;
95 unsigned char *penc;
96
97 if (xkey == NULL) {
98 ECerr(EC_F_ECX_PUB_ENCODE, EC_R_INVALID_KEY);
99 return 0;
100 }
101
102 penc = OPENSSL_memdup(xkey->pubkey, X25519_KEYLEN);
103 if (penc == NULL) {
104 ECerr(EC_F_ECX_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
105 return 0;
106 }
107
108 if (!X509_PUBKEY_set0_param(pk, OBJ_nid2obj(NID_X25519), V_ASN1_UNDEF,
109 NULL, penc, X25519_KEYLEN)) {
110 OPENSSL_free(penc);
111 ECerr(EC_F_ECX_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
112 return 0;
113 }
114 return 1;
115}
116
117static int ecx_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
118{
119 const unsigned char *p;
120 int pklen;
121 X509_ALGOR *palg;
122
123 if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
124 return 0;
125 return ecx_key_op(pkey, palg, p, pklen, X25519_PUBLIC);
126}
127
128static int ecx_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
129{
130 const X25519_KEY *akey = a->pkey.ptr;
131 const X25519_KEY *bkey = b->pkey.ptr;
132
133 if (akey == NULL || bkey == NULL)
134 return -2;
135 return !CRYPTO_memcmp(akey->pubkey, bkey->pubkey, X25519_KEYLEN);
136}
137
138static int ecx_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
139{
140 const unsigned char *p;
141 int plen;
142 ASN1_OCTET_STRING *oct = NULL;
143 const X509_ALGOR *palg;
144 int rv;
145
146 if (!PKCS8_pkey_get0(NULL, &p, &plen, &palg, p8))
147 return 0;
148
149 oct = d2i_ASN1_OCTET_STRING(NULL, &p, plen);
150 if (oct == NULL) {
151 p = NULL;
152 plen = 0;
153 } else {
154 p = ASN1_STRING_get0_data(oct);
155 plen = ASN1_STRING_length(oct);
156 }
157
158 rv = ecx_key_op(pkey, palg, p, plen, X25519_PRIVATE);
159 ASN1_OCTET_STRING_free(oct);
160 return rv;
161}
162
163static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
164{
165 const X25519_KEY *xkey = pkey->pkey.ptr;
166 ASN1_OCTET_STRING oct;
167 unsigned char *penc = NULL;
168 int penclen;
169
170 if (xkey == NULL || xkey->privkey == NULL) {
171 ECerr(EC_F_ECX_PRIV_ENCODE, EC_R_INVALID_PRIVATE_KEY);
172 return 0;
173 }
174
175 oct.data = xkey->privkey;
176 oct.length = X25519_KEYLEN;
177 oct.flags = 0;
178
179 penclen = i2d_ASN1_OCTET_STRING(&oct, &penc);
180 if (penclen < 0) {
181 ECerr(EC_F_ECX_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
182 return 0;
183 }
184
185 if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X25519), 0,
186 V_ASN1_UNDEF, NULL, penc, penclen)) {
187 OPENSSL_clear_free(penc, penclen);
188 ECerr(EC_F_ECX_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
189 return 0;
190 }
191
192 return 1;
193}
194
195static int ecx_size(const EVP_PKEY *pkey)
196{
197 return X25519_KEYLEN;
198}
199
200static int ecx_bits(const EVP_PKEY *pkey)
201{
202 return X25519_BITS;
203}
204
205static int ecx_security_bits(const EVP_PKEY *pkey)
206{
207 return X25519_SECURITY_BITS;
208}
209
210static void ecx_free(EVP_PKEY *pkey)
211{
212 X25519_KEY *xkey = pkey->pkey.ptr;
213
214 if (xkey)
215 OPENSSL_secure_free(xkey->privkey);
216 OPENSSL_free(xkey);
217}
218
219/* "parameters" are always equal */
220static int ecx_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
221{
222 return 1;
223}
224
225static int ecx_key_print(BIO *bp, const EVP_PKEY *pkey, int indent,
226 ASN1_PCTX *ctx, ecx_key_op_t op)
227{
228 const X25519_KEY *xkey = pkey->pkey.ptr;
229
230 if (op == X25519_PRIVATE) {
231 if (xkey == NULL || xkey->privkey == NULL) {
232 if (BIO_printf(bp, "%*s<INVALID PRIVATE KEY>\n", indent, "") <= 0)
233 return 0;
234 return 1;
235 }
236 if (BIO_printf(bp, "%*sX25519 Private-Key:\n", indent, "") <= 0)
237 return 0;
238 if (BIO_printf(bp, "%*spriv:\n", indent, "") <= 0)
239 return 0;
240 if (ASN1_buf_print(bp, xkey->privkey, X25519_KEYLEN, indent + 4) == 0)
241 return 0;
242 } else {
243 if (xkey == NULL) {
244 if (BIO_printf(bp, "%*s<INVALID PUBLIC KEY>\n", indent, "") <= 0)
245 return 0;
246 return 1;
247 }
248 if (BIO_printf(bp, "%*sX25519 Public-Key:\n", indent, "") <= 0)
249 return 0;
250 }
251 if (BIO_printf(bp, "%*spub:\n", indent, "") <= 0)
252 return 0;
253 if (ASN1_buf_print(bp, xkey->pubkey, X25519_KEYLEN, indent + 4) == 0)
254 return 0;
255 return 1;
256}
257
258static int ecx_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
259 ASN1_PCTX *ctx)
260{
261 return ecx_key_print(bp, pkey, indent, ctx, X25519_PRIVATE);
262}
263
264static int ecx_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
265 ASN1_PCTX *ctx)
266{
267 return ecx_key_print(bp, pkey, indent, ctx, X25519_PUBLIC);
268}
269
270static int ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
271{
272 switch (op) {
273
274 case ASN1_PKEY_CTRL_SET1_TLS_ENCPT:
275 return ecx_key_op(pkey, NULL, arg2, arg1, X25519_PUBLIC);
276
277 case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
278 if (pkey->pkey.ptr != NULL) {
279 const X25519_KEY *xkey = pkey->pkey.ptr;
280 unsigned char **ppt = arg2;
281 *ppt = OPENSSL_memdup(xkey->pubkey, X25519_KEYLEN);
282 if (*ppt != NULL)
283 return X25519_KEYLEN;
284 }
285 return 0;
286
287 case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
288 *(int *)arg2 = NID_sha256;
289 return 2;
290
291 default:
292 return -2;
293
294 }
295}
296
297const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth = {
298 NID_X25519,
299 NID_X25519,
300 0,
301 "X25519",
302 "OpenSSL X25519 algorithm",
303
304 ecx_pub_decode,
305 ecx_pub_encode,
306 ecx_pub_cmp,
307 ecx_pub_print,
308
309 ecx_priv_decode,
310 ecx_priv_encode,
311 ecx_priv_print,
312
313 ecx_size,
314 ecx_bits,
315 ecx_security_bits,
316
317 0, 0, 0, 0,
318 ecx_cmp_parameters,
319 0, 0,
320
321 ecx_free,
322 ecx_ctrl,
323 NULL,
324 NULL
325};
326
327static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
328{
329 return ecx_key_op(pkey, NULL, NULL, 0, X25519_KEYGEN);
330}
331
332static int pkey_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
333 size_t *keylen)
334{
335 const X25519_KEY *pkey, *peerkey;
336
337 if (ctx->pkey == NULL || ctx->peerkey == NULL) {
338 ECerr(EC_F_PKEY_ECX_DERIVE, EC_R_KEYS_NOT_SET);
339 return 0;
340 }
341 pkey = ctx->pkey->pkey.ptr;
342 peerkey = ctx->peerkey->pkey.ptr;
343 if (pkey == NULL || pkey->privkey == NULL) {
344 ECerr(EC_F_PKEY_ECX_DERIVE, EC_R_INVALID_PRIVATE_KEY);
345 return 0;
346 }
347 if (peerkey == NULL) {
348 ECerr(EC_F_PKEY_ECX_DERIVE, EC_R_INVALID_PEER_KEY);
349 return 0;
350 }
351 *keylen = X25519_KEYLEN;
352 if (key != NULL && X25519(key, pkey->privkey, peerkey->pubkey) == 0)
353 return 0;
354 return 1;
355}
356
357static int pkey_ecx_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
358{
359 /* Only need to handle peer key for derivation */
360 if (type == EVP_PKEY_CTRL_PEER_KEY)
361 return 1;
362 return -2;
363}
364
365const EVP_PKEY_METHOD ecx25519_pkey_meth = {
366 NID_X25519,
367 0, 0, 0, 0, 0, 0, 0,
368 pkey_ecx_keygen,
369 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
370 pkey_ecx_derive,
371 pkey_ecx_ctrl,
372 0
373};
Note: See TracBrowser for help on using the repository browser.