Annotation of embedaddon/strongswan/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2017 Tobias Brunner
3: * Copyright (C) 2005-2009 Martin Willi
4: * HSR Hochschule fuer Technik Rapperswil
5: *
6: * This program is free software; you can redistribute it and/or modify it
7: * under the terms of the GNU General Public License as published by the
8: * Free Software Foundation; either version 2 of the License, or (at your
9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10: *
11: * This program is distributed in the hope that it will be useful, but
12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14: * for more details.
15: */
16:
17: #include <gcrypt.h>
18:
19: #include "gcrypt_rsa_public_key.h"
20:
21: #include <utils/debug.h>
22: #include <asn1/oid.h>
23: #include <asn1/asn1.h>
24: #include <asn1/asn1_parser.h>
25: #include <crypto/hashers/hasher.h>
26: #include <credentials/keys/signature_params.h>
27:
28: typedef struct private_gcrypt_rsa_public_key_t private_gcrypt_rsa_public_key_t;
29:
30: /**
31: * Private data structure with signing context.
32: */
33: struct private_gcrypt_rsa_public_key_t {
34:
35: /**
36: * Public interface for this signer.
37: */
38: gcrypt_rsa_public_key_t public;
39:
40: /**
41: * gcrypt S-expression representing an public RSA key
42: */
43: gcry_sexp_t key;
44:
45: /**
46: * reference counter
47: */
48: refcount_t ref;
49: };
50:
51: /**
52: * Implemented in gcrypt_rsa_private_key.c
53: */
54: chunk_t gcrypt_rsa_find_token(gcry_sexp_t sexp, char *name, gcry_sexp_t key);
55:
56: /**
57: * verification of a padded PKCS1 signature without an OID
58: */
59: static bool verify_raw(private_gcrypt_rsa_public_key_t *this,
60: chunk_t data, chunk_t signature)
61: {
62: gcry_sexp_t in, sig;
63: gcry_error_t err;
64: chunk_t em;
65: size_t k;
66:
67: /* EM = 0x00 || 0x01 || PS || 0x00 || T
68: * PS = 0xFF padding, with length to fill em
69: * T = data
70: */
71: k = gcry_pk_get_nbits(this->key) / 8;
72: if (data.len > k - 3)
73: {
74: return FALSE;
75: }
76: em = chunk_alloc(k);
77: memset(em.ptr, 0xFF, em.len);
78: em.ptr[0] = 0x00;
79: em.ptr[1] = 0x01;
80: em.ptr[em.len - data.len - 1] = 0x00;
81: memcpy(em.ptr + em.len - data.len, data.ptr, data.len);
82:
83: err = gcry_sexp_build(&in, NULL, "(data(flags raw)(value %b))",
84: em.len, em.ptr);
85: chunk_free(&em);
86: if (err)
87: {
88: DBG1(DBG_LIB, "building data S-expression failed: %s",
89: gpg_strerror(err));
90: return FALSE;
91: }
92: err = gcry_sexp_build(&sig, NULL, "(sig-val(rsa(s %b)))",
93: signature.len, signature.ptr);
94: if (err)
95: {
96: DBG1(DBG_LIB, "building signature S-expression failed: %s",
97: gpg_strerror(err));
98: gcry_sexp_release(in);
99: return FALSE;
100: }
101: err = gcry_pk_verify(sig, in, this->key);
102: gcry_sexp_release(in);
103: gcry_sexp_release(sig);
104: if (err)
105: {
106: DBG1(DBG_LIB, "RSA signature verification failed: %s",
107: gpg_strerror(err));
108: return FALSE;
109: }
110: return TRUE;
111: }
112:
113: /**
114: * Verification of an EMSA PKCS1v1.5 / EMSA-PSS signature described in PKCS#1
115: */
116: static bool verify_pkcs1(private_gcrypt_rsa_public_key_t *this,
117: hash_algorithm_t algorithm, rsa_pss_params_t *pss,
118: chunk_t data, chunk_t signature)
119: {
120: hasher_t *hasher;
121: chunk_t hash;
122: gcry_error_t err;
123: gcry_sexp_t in, sig;
124: char *hash_name = enum_to_name(hash_algorithm_short_names, algorithm);
125:
126: hasher = lib->crypto->create_hasher(lib->crypto, algorithm);
127: if (!hasher)
128: {
129: DBG1(DBG_LIB, "hash algorithm %N not supported",
130: hash_algorithm_names, algorithm);
131: return FALSE;
132: }
133: if (!hasher->allocate_hash(hasher, data, &hash))
134: {
135: hasher->destroy(hasher);
136: return FALSE;
137: }
138: hasher->destroy(hasher);
139:
140: if (pss)
141: {
142: u_int slen = pss->salt_len;
143: err = gcry_sexp_build(&in, NULL,
144: "(data(flags pss)(salt-length %u)(hash %s %b))",
145: slen, hash_name, hash.len, hash.ptr);
146: }
147: else
148: {
149: err = gcry_sexp_build(&in, NULL, "(data(flags pkcs1)(hash %s %b))",
150: hash_name, hash.len, hash.ptr);
151: }
152: chunk_free(&hash);
153: if (err)
154: {
155: DBG1(DBG_LIB, "building data S-expression failed: %s",
156: gpg_strerror(err));
157: return FALSE;
158: }
159:
160: err = gcry_sexp_build(&sig, NULL, "(sig-val(rsa(s %b)))",
161: signature.len, signature.ptr);
162: if (err)
163: {
164: DBG1(DBG_LIB, "building signature S-expression failed: %s",
165: gpg_strerror(err));
166: gcry_sexp_release(in);
167: return FALSE;
168: }
169: err = gcry_pk_verify(sig, in, this->key);
170: gcry_sexp_release(in);
171: gcry_sexp_release(sig);
172: if (err)
173: {
174: DBG1(DBG_LIB, "RSA signature verification failed: %s",
175: gpg_strerror(err));
176: return FALSE;
177: }
178: return TRUE;
179: }
180:
181: #if GCRYPT_VERSION_NUMBER >= 0x010700
182: /**
183: * Verification of an EMSA-PSS signature described in PKCS#1
184: */
185: static bool verify_pss(private_gcrypt_rsa_public_key_t *this,
186: rsa_pss_params_t *params, chunk_t data, chunk_t sig)
187: {
188: if (!params)
189: {
190: return FALSE;
191: }
192: if (params->mgf1_hash != params->hash)
193: {
194: DBG1(DBG_LIB, "unable to use a different MGF1 hash for RSA-PSS");
195: return FALSE;
196: }
197: return verify_pkcs1(this, params->hash, params, data, sig);
198: }
199: #endif
200:
201: METHOD(public_key_t, get_type, key_type_t,
202: private_gcrypt_rsa_public_key_t *this)
203: {
204: return KEY_RSA;
205: }
206:
207: METHOD(public_key_t, verify, bool,
208: private_gcrypt_rsa_public_key_t *this, signature_scheme_t scheme,
209: void *params, chunk_t data, chunk_t signature)
210: {
211: switch (scheme)
212: {
213: case SIGN_RSA_EMSA_PKCS1_NULL:
214: return verify_raw(this, data, signature);
215: case SIGN_RSA_EMSA_PKCS1_SHA2_224:
216: return verify_pkcs1(this, HASH_SHA224, NULL, data, signature);
217: case SIGN_RSA_EMSA_PKCS1_SHA2_256:
218: return verify_pkcs1(this, HASH_SHA256, NULL, data, signature);
219: case SIGN_RSA_EMSA_PKCS1_SHA2_384:
220: return verify_pkcs1(this, HASH_SHA384, NULL, data, signature);
221: case SIGN_RSA_EMSA_PKCS1_SHA2_512:
222: return verify_pkcs1(this, HASH_SHA512, NULL, data, signature);
223: case SIGN_RSA_EMSA_PKCS1_SHA1:
224: return verify_pkcs1(this, HASH_SHA1, NULL, data, signature);
225: case SIGN_RSA_EMSA_PKCS1_MD5:
226: return verify_pkcs1(this, HASH_MD5, NULL, data, signature);
227: #if GCRYPT_VERSION_NUMBER >= 0x010700
228: case SIGN_RSA_EMSA_PSS:
229: return verify_pss(this, params, data, signature);
230: #endif
231: default:
232: DBG1(DBG_LIB, "signature scheme %N not supported in RSA",
233: signature_scheme_names, scheme);
234: return FALSE;
235: }
236: }
237:
238: METHOD(public_key_t, encrypt_, bool,
239: private_gcrypt_rsa_public_key_t *this, encryption_scheme_t scheme,
240: chunk_t plain, chunk_t *encrypted)
241: {
242: gcry_sexp_t in, out;
243: gcry_error_t err;
244:
245: if (scheme != ENCRYPT_RSA_PKCS1)
246: {
247: DBG1(DBG_LIB, "encryption scheme %N not supported",
248: encryption_scheme_names, scheme);
249: return FALSE;
250: }
251: /* "pkcs1" uses PKCS 1.5 (section 8.1) block type 2 encryption:
252: * 00 | 02 | RANDOM | 00 | DATA */
253: err = gcry_sexp_build(&in, NULL, "(data(flags pkcs1)(value %b))",
254: plain.len, plain.ptr);
255: if (err)
256: {
257: DBG1(DBG_LIB, "building encryption S-expression failed: %s",
258: gpg_strerror(err));
259: return FALSE;
260: }
261: err = gcry_pk_encrypt(&out, in, this->key);
262: gcry_sexp_release(in);
263: if (err)
264: {
265: DBG1(DBG_LIB, "encrypting data using pkcs1 failed: %s",
266: gpg_strerror(err));
267: return FALSE;
268: }
269: *encrypted = gcrypt_rsa_find_token(out, "a", this->key);
270: gcry_sexp_release(out);
271: return !!encrypted->len;
272: }
273:
274: METHOD(public_key_t, get_keysize, int,
275: private_gcrypt_rsa_public_key_t *this)
276: {
277: return gcry_pk_get_nbits(this->key);
278: }
279:
280: METHOD(public_key_t, get_encoding, bool,
281: private_gcrypt_rsa_public_key_t *this, cred_encoding_type_t type,
282: chunk_t *encoding)
283: {
284: chunk_t n, e;
285: bool success;
286:
287: n = gcrypt_rsa_find_token(this->key, "n", NULL);
288: e = gcrypt_rsa_find_token(this->key, "e", NULL);
289: success = lib->encoding->encode(lib->encoding, type, NULL, encoding,
290: CRED_PART_RSA_MODULUS, n, CRED_PART_RSA_PUB_EXP, e,
291: CRED_PART_END);
292: chunk_free(&n);
293: chunk_free(&e);
294:
295: return success;
296: }
297:
298: METHOD(public_key_t, get_fingerprint, bool,
299: private_gcrypt_rsa_public_key_t *this, cred_encoding_type_t type,
300: chunk_t *fp)
301: {
302: chunk_t n, e;
303: bool success;
304:
305: if (lib->encoding->get_cache(lib->encoding, type, this, fp))
306: {
307: return TRUE;
308: }
309: n = gcrypt_rsa_find_token(this->key, "n", NULL);
310: e = gcrypt_rsa_find_token(this->key, "e", NULL);
311:
312: success = lib->encoding->encode(lib->encoding,
313: type, this, fp, CRED_PART_RSA_MODULUS, n,
314: CRED_PART_RSA_PUB_EXP, e, CRED_PART_END);
315: chunk_free(&n);
316: chunk_free(&e);
317: return success;
318: }
319:
320: METHOD(public_key_t, get_ref, public_key_t*,
321: private_gcrypt_rsa_public_key_t *this)
322: {
323: ref_get(&this->ref);
324: return &this->public.key;
325: }
326:
327: METHOD(public_key_t, destroy, void,
328: private_gcrypt_rsa_public_key_t *this)
329: {
330: if (ref_put(&this->ref))
331: {
332: gcry_sexp_release(this->key);
333: lib->encoding->clear_cache(lib->encoding, this);
334: free(this);
335: }
336: }
337:
338: /**
339: * See header.
340: */
341: gcrypt_rsa_public_key_t *gcrypt_rsa_public_key_load(key_type_t type,
342: va_list args)
343: {
344: private_gcrypt_rsa_public_key_t *this;
345: gcry_error_t err;
346: chunk_t n, e;
347:
348: n = e = chunk_empty;
349: while (TRUE)
350: {
351: switch (va_arg(args, builder_part_t))
352: {
353: case BUILD_RSA_MODULUS:
354: n = va_arg(args, chunk_t);
355: continue;
356: case BUILD_RSA_PUB_EXP:
357: e = va_arg(args, chunk_t);
358: continue;
359: case BUILD_END:
360: break;
361: default:
362: return NULL;
363: }
364: break;
365: }
366:
367: INIT(this,
368: .public = {
369: .key = {
370: .get_type = _get_type,
371: .verify = _verify,
372: .encrypt = _encrypt_,
373: .equals = public_key_equals,
374: .get_keysize = _get_keysize,
375: .get_fingerprint = _get_fingerprint,
376: .has_fingerprint = public_key_has_fingerprint,
377: .get_encoding = _get_encoding,
378: .get_ref = _get_ref,
379: .destroy = _destroy,
380: },
381: },
382: .ref = 1,
383: );
384:
385: err = gcry_sexp_build(&this->key, NULL, "(public-key(rsa(n %b)(e %b)))",
386: n.len, n.ptr, e.len, e.ptr);
387: if (err)
388: {
389: DBG1(DBG_LIB, "loading public key failed: %s", gpg_strerror(err));
390: free(this);
391: return NULL;
392: }
393:
394: return &this->public;
395: }
396:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>