Annotation of embedaddon/strongswan/src/libstrongswan/plugins/openssl/openssl_ed_private_key.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2018 Tobias Brunner
3: * HSR Hochschule fuer Technik Rapperswil
4: *
5: * This program is free software; you can redistribute it and/or modify it
6: * under the terms of the GNU General Public License as published by the
7: * Free Software Foundation; either version 2 of the License, or (at your
8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9: *
10: * This program is distributed in the hope that it will be useful, but
11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13: * for more details.
14: */
15:
16: #include <openssl/evp.h>
17:
18: #if OPENSSL_VERSION_NUMBER >= 0x1010100fL && !defined(OPENSSL_NO_EC)
19:
20: #include "openssl_ed_private_key.h"
21:
22: #include <utils/debug.h>
23:
24: typedef struct private_private_key_t private_private_key_t;
25:
26: /**
27: * Private data
28: */
29: struct private_private_key_t {
30:
31: /**
32: * Public interface
33: */
34: private_key_t public;
35:
36: /**
37: * Key object
38: */
39: EVP_PKEY *key;
40:
41: /**
42: * Key type
43: */
44: key_type_t type;
45:
46: /**
47: * TRUE if the key is from an OpenSSL ENGINE and might not be readable
48: */
49: bool engine;
50:
51: /**
52: * reference count
53: */
54: refcount_t ref;
55: };
56:
57: /**
58: * We can't include asn1.h, declare function prototype directly
59: */
60: int asn1_unwrap(chunk_t*, chunk_t*);
61:
62: /* from ed public key */
63: int openssl_ed_key_type(key_type_t type);
64: int openssl_ed_keysize(key_type_t type);
65: bool openssl_ed_fingerprint(EVP_PKEY *key, cred_encoding_type_t type, chunk_t *fp);
66:
67: METHOD(private_key_t, sign, bool,
68: private_private_key_t *this, signature_scheme_t scheme,
69: void *params, chunk_t data, chunk_t *signature)
70: {
71: EVP_MD_CTX *ctx;
72: bool success = FALSE;
73:
74: if ((this->type == KEY_ED25519 && scheme != SIGN_ED25519) ||
75: (this->type == KEY_ED448 && scheme != SIGN_ED448))
76: {
77: DBG1(DBG_LIB, "signature scheme %N not supported by %N key",
78: signature_scheme_names, scheme, key_type_names, this->type);
79: return FALSE;
80: }
81:
82: ctx = EVP_MD_CTX_new();
83: if (!ctx ||
84: EVP_DigestSignInit(ctx, NULL, NULL, NULL, this->key) <= 0)
85: {
86: goto error;
87: }
88:
89: if (EVP_DigestSign(ctx, NULL, &signature->len, data.ptr, data.len) <= 0)
90: {
91: goto error;
92: }
93:
94: *signature = chunk_alloc(signature->len);
95:
96: if (EVP_DigestSign(ctx, signature->ptr, &signature->len,
97: data.ptr, data.len) <= 0)
98: {
99: goto error;
100: }
101:
102: success = TRUE;
103:
104: error:
105: EVP_MD_CTX_free(ctx);
106: return success;
107: }
108:
109: METHOD(private_key_t, decrypt, bool,
110: private_private_key_t *this, encryption_scheme_t scheme,
111: chunk_t crypto, chunk_t *plain)
112: {
113: DBG1(DBG_LIB, "EdDSA private key decryption not implemented");
114: return FALSE;
115: }
116:
117: METHOD(private_key_t, get_keysize, int,
118: private_private_key_t *this)
119: {
120: return openssl_ed_keysize(this->type);
121: }
122:
123: METHOD(private_key_t, get_type, key_type_t,
124: private_private_key_t *this)
125: {
126: return this->type;
127: }
128:
129: METHOD(private_key_t, get_public_key, public_key_t*,
130: private_private_key_t *this)
131: {
132: public_key_t *public;
133: chunk_t key;
134:
135: if (!EVP_PKEY_get_raw_public_key(this->key, NULL, &key.len))
136: {
137: return FALSE;
138: }
139: key = chunk_alloca(key.len);
140: if (!EVP_PKEY_get_raw_public_key(this->key, key.ptr, &key.len))
141: {
142: return FALSE;
143: }
144: public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, this->type,
145: BUILD_EDDSA_PUB, key, BUILD_END);
146: return public;
147: }
148:
149: METHOD(private_key_t, get_fingerprint, bool,
150: private_private_key_t *this, cred_encoding_type_t type,
151: chunk_t *fingerprint)
152: {
153: return openssl_ed_fingerprint(this->key, type, fingerprint);
154: }
155:
156: METHOD(private_key_t, get_encoding, bool,
157: private_private_key_t *this, cred_encoding_type_t type, chunk_t *encoding)
158: {
159: u_char *p;
160:
161: if (this->engine)
162: {
163: return FALSE;
164: }
165:
166: switch (type)
167: {
168: case PRIVKEY_ASN1_DER:
169: case PRIVKEY_PEM:
170: {
171: bool success = TRUE;
172:
173: *encoding = chunk_alloc(i2d_PrivateKey(this->key, NULL));
174: p = encoding->ptr;
175: i2d_PrivateKey(this->key, &p);
176:
177: if (type == PRIVKEY_PEM)
178: {
179: chunk_t asn1_encoding = *encoding;
180:
181: success = lib->encoding->encode(lib->encoding, PRIVKEY_PEM,
182: NULL, encoding, CRED_PART_EDDSA_PRIV_ASN1_DER,
183: asn1_encoding, CRED_PART_END);
184: chunk_clear(&asn1_encoding);
185: }
186: return success;
187: }
188: default:
189: return FALSE;
190: }
191: }
192:
193: METHOD(private_key_t, get_ref, private_key_t*,
194: private_private_key_t *this)
195: {
196: ref_get(&this->ref);
197: return &this->public;
198: }
199:
200: METHOD(private_key_t, destroy, void,
201: private_private_key_t *this)
202: {
203: if (ref_put(&this->ref))
204: {
205: lib->encoding->clear_cache(lib->encoding, this->key);
206: EVP_PKEY_free(this->key);
207: free(this);
208: }
209: }
210:
211: /**
212: * Internal generic constructor
213: */
214: static private_private_key_t *create_internal(key_type_t type, EVP_PKEY *key)
215: {
216: private_private_key_t *this;
217:
218: INIT(this,
219: .public = {
220: .get_type = _get_type,
221: .sign = _sign,
222: .decrypt = _decrypt,
223: .get_keysize = _get_keysize,
224: .get_public_key = _get_public_key,
225: .equals = private_key_equals,
226: .belongs_to = private_key_belongs_to,
227: .get_fingerprint = _get_fingerprint,
228: .has_fingerprint = private_key_has_fingerprint,
229: .get_encoding = _get_encoding,
230: .get_ref = _get_ref,
231: .destroy = _destroy,
232: },
233: .type = type,
234: .key = key,
235: .ref = 1,
236: );
237:
238: return this;
239: }
240:
241: /*
242: * Described in header
243: */
244: private_key_t *openssl_ed_private_key_create(EVP_PKEY *key, bool engine)
245: {
246: private_private_key_t *this;
247: key_type_t type;
248:
249: switch (EVP_PKEY_base_id(key))
250: {
251: case EVP_PKEY_X25519:
252: type = KEY_ED25519;
253: break;
254: case EVP_PKEY_X448:
255: type = KEY_ED448;
256: break;
257: default:
258: EVP_PKEY_free(key);
259: return NULL;
260: }
261:
262: this = create_internal(type, key);
263: this->engine = engine;
264: return &this->public;
265: }
266:
267: /*
268: * Described in header
269: */
270: private_key_t *openssl_ed_private_key_gen(key_type_t type, va_list args)
271: {
272: private_private_key_t *this;
273: EVP_PKEY_CTX *ctx;
274: EVP_PKEY *key = NULL;
275:
276: while (TRUE)
277: {
278: switch (va_arg(args, builder_part_t))
279: {
280: case BUILD_KEY_SIZE:
281: /* just ignore the key size */
282: va_arg(args, u_int);
283: continue;
284: case BUILD_END:
285: break;
286: default:
287: return NULL;
288: }
289: break;
290: }
291:
292: ctx = EVP_PKEY_CTX_new_id(openssl_ed_key_type(type), NULL);
293: if (!ctx ||
294: EVP_PKEY_keygen_init(ctx) <= 0 ||
295: EVP_PKEY_keygen(ctx, &key) <= 0)
296: {
297: DBG1(DBG_LIB, "generating %N key failed", key_type_names, type);
298: EVP_PKEY_CTX_free(ctx);
299: return NULL;
300: }
301: EVP_PKEY_CTX_free(ctx);
302:
303: this = create_internal(type, key);
304: return &this->public;
305: }
306:
307: /*
308: * Described in header
309: */
310: private_key_t *openssl_ed_private_key_load(key_type_t type, va_list args)
311: {
312: private_private_key_t *this;
313: chunk_t blob = chunk_empty, priv = chunk_empty;
314: EVP_PKEY *key = NULL;
315:
316: while (TRUE)
317: {
318: switch (va_arg(args, builder_part_t))
319: {
320: case BUILD_BLOB_ASN1_DER:
321: blob = va_arg(args, chunk_t);
322: continue;
323: case BUILD_EDDSA_PRIV_ASN1_DER:
324: priv = va_arg(args, chunk_t);
325: continue;
326: case BUILD_END:
327: break;
328: default:
329: return NULL;
330: }
331: break;
332: }
333:
334: if (priv.len)
335: {
336: /* unwrap octet string */
337: if (asn1_unwrap(&priv, &priv) == 0x04 && priv.len)
338: {
339: key = EVP_PKEY_new_raw_private_key(openssl_ed_key_type(type), NULL,
340: priv.ptr, priv.len);
341: }
342: }
343: else if (blob.len)
344: {
345: key = d2i_PrivateKey(openssl_ed_key_type(type), NULL,
346: (const u_char**)&blob.ptr, blob.len);
347: }
348: if (!key)
349: {
350: return NULL;
351: }
352: this = create_internal(type, key);
353: return &this->public;
354: }
355:
356: #endif /* OPENSSL_NO_ECDSA */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>