2 * Copyright (C) 2017 Tobias Brunner
3 * Copyright (C) 2005-2009 Martin Willi
4 * HSR Hochschule fuer Technik Rapperswil
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>.
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
19 #include "gcrypt_rsa_public_key.h"
21 #include <utils/debug.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>
28 typedef struct private_gcrypt_rsa_public_key_t private_gcrypt_rsa_public_key_t
;
31 * Private data structure with signing context.
33 struct private_gcrypt_rsa_public_key_t
{
36 * Public interface for this signer.
38 gcrypt_rsa_public_key_t
public;
41 * gcrypt S-expression representing an public RSA key
52 * Implemented in gcrypt_rsa_private_key.c
54 chunk_t
gcrypt_rsa_find_token(gcry_sexp_t sexp
, char *name
, gcry_sexp_t key
);
57 * verification of a padded PKCS1 signature without an OID
59 static bool verify_raw(private_gcrypt_rsa_public_key_t
*this,
60 chunk_t data
, chunk_t signature
)
67 /* EM = 0x00 || 0x01 || PS || 0x00 || T
68 * PS = 0xFF padding, with length to fill em
71 k
= gcry_pk_get_nbits(this->key
) / 8;
77 memset(em
.ptr
, 0xFF, em
.len
);
80 em
.ptr
[em
.len
- data
.len
- 1] = 0x00;
81 memcpy(em
.ptr
+ em
.len
- data
.len
, data
.ptr
, data
.len
);
83 err
= gcry_sexp_build(&in
, NULL
, "(data(flags raw)(value %b))",
88 DBG1(DBG_LIB
, "building data S-expression failed: %s",
92 err
= gcry_sexp_build(&sig
, NULL
, "(sig-val(rsa(s %b)))",
93 signature
.len
, signature
.ptr
);
96 DBG1(DBG_LIB
, "building signature S-expression failed: %s",
98 gcry_sexp_release(in
);
101 err
= gcry_pk_verify(sig
, in
, this->key
);
102 gcry_sexp_release(in
);
103 gcry_sexp_release(sig
);
106 DBG1(DBG_LIB
, "RSA signature verification failed: %s",
114 * Verification of an EMSA PKCS1v1.5 / EMSA-PSS signature described in PKCS#1
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
)
124 char *hash_name
= enum_to_name(hash_algorithm_short_names
, algorithm
);
126 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, algorithm
);
129 DBG1(DBG_LIB
, "hash algorithm %N not supported",
130 hash_algorithm_names
, algorithm
);
133 if (!hasher
->allocate_hash(hasher
, data
, &hash
))
135 hasher
->destroy(hasher
);
138 hasher
->destroy(hasher
);
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
);
149 err
= gcry_sexp_build(&in
, NULL
, "(data(flags pkcs1)(hash %s %b))",
150 hash_name
, hash
.len
, hash
.ptr
);
155 DBG1(DBG_LIB
, "building data S-expression failed: %s",
160 err
= gcry_sexp_build(&sig
, NULL
, "(sig-val(rsa(s %b)))",
161 signature
.len
, signature
.ptr
);
164 DBG1(DBG_LIB
, "building signature S-expression failed: %s",
166 gcry_sexp_release(in
);
169 err
= gcry_pk_verify(sig
, in
, this->key
);
170 gcry_sexp_release(in
);
171 gcry_sexp_release(sig
);
174 DBG1(DBG_LIB
, "RSA signature verification failed: %s",
181 #if GCRYPT_VERSION_NUMBER >= 0x010700
183 * Verification of an EMSA-PSS signature described in PKCS#1
185 static bool verify_pss(private_gcrypt_rsa_public_key_t
*this,
186 rsa_pss_params_t
*params
, chunk_t data
, chunk_t sig
)
192 if (params
->mgf1_hash
!= params
->hash
)
194 DBG1(DBG_LIB
, "unable to use a different MGF1 hash for RSA-PSS");
197 return verify_pkcs1(this, params
->hash
, params
, data
, sig
);
201 METHOD(public_key_t
, get_type
, key_type_t
,
202 private_gcrypt_rsa_public_key_t
*this)
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
)
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
);
232 DBG1(DBG_LIB
, "signature scheme %N not supported in RSA",
233 signature_scheme_names
, scheme
);
238 METHOD(public_key_t
, encrypt_
, bool,
239 private_gcrypt_rsa_public_key_t
*this, encryption_scheme_t scheme
,
240 void *params
, chunk_t plain
, chunk_t
*encrypted
)
244 chunk_t label
= chunk_empty
;
249 case ENCRYPT_RSA_PKCS1
:
250 sexp
= "(data(flags pkcs1)(value %b))";
252 case ENCRYPT_RSA_OAEP_SHA1
:
253 sexp
= "(data(flags oaep)(value %b))";
256 DBG1(DBG_LIB
, "encryption scheme %N not supported",
257 encryption_scheme_names
, scheme
);
261 if (scheme
== ENCRYPT_RSA_OAEP_SHA1
&& params
!= NULL
)
263 label
= *(chunk_t
*)params
;
266 DBG1(DBG_LIB
, "RSA OAEP encryption with a label not supported");
271 err
= gcry_sexp_build(&in
, NULL
, sexp
, plain
.len
, plain
.ptr
);
274 DBG1(DBG_LIB
, "building encryption S-expression failed: %s",
279 err
= gcry_pk_encrypt(&out
, in
, this->key
);
280 gcry_sexp_release(in
);
283 DBG1(DBG_LIB
, "RSA encryption failed: %s", gpg_strerror(err
));
287 *encrypted
= gcrypt_rsa_find_token(out
, "a", this->key
);
288 gcry_sexp_release(out
);
290 return encrypted
->len
> 0;
293 METHOD(public_key_t
, get_keysize
, int,
294 private_gcrypt_rsa_public_key_t
*this)
296 return gcry_pk_get_nbits(this->key
);
299 METHOD(public_key_t
, get_encoding
, bool,
300 private_gcrypt_rsa_public_key_t
*this, cred_encoding_type_t type
,
306 n
= gcrypt_rsa_find_token(this->key
, "n", NULL
);
307 e
= gcrypt_rsa_find_token(this->key
, "e", NULL
);
308 success
= lib
->encoding
->encode(lib
->encoding
, type
, NULL
, encoding
,
309 CRED_PART_RSA_MODULUS
, n
, CRED_PART_RSA_PUB_EXP
, e
,
317 METHOD(public_key_t
, get_fingerprint
, bool,
318 private_gcrypt_rsa_public_key_t
*this, cred_encoding_type_t type
,
324 if (lib
->encoding
->get_cache(lib
->encoding
, type
, this, fp
))
328 n
= gcrypt_rsa_find_token(this->key
, "n", NULL
);
329 e
= gcrypt_rsa_find_token(this->key
, "e", NULL
);
331 success
= lib
->encoding
->encode(lib
->encoding
,
332 type
, this, fp
, CRED_PART_RSA_MODULUS
, n
,
333 CRED_PART_RSA_PUB_EXP
, e
, CRED_PART_END
);
339 METHOD(public_key_t
, get_ref
, public_key_t
*,
340 private_gcrypt_rsa_public_key_t
*this)
343 return &this->public.key
;
346 METHOD(public_key_t
, destroy
, void,
347 private_gcrypt_rsa_public_key_t
*this)
349 if (ref_put(&this->ref
))
351 gcry_sexp_release(this->key
);
352 lib
->encoding
->clear_cache(lib
->encoding
, this);
360 gcrypt_rsa_public_key_t
*gcrypt_rsa_public_key_load(key_type_t type
,
363 private_gcrypt_rsa_public_key_t
*this;
370 switch (va_arg(args
, builder_part_t
))
372 case BUILD_RSA_MODULUS
:
373 n
= va_arg(args
, chunk_t
);
375 case BUILD_RSA_PUB_EXP
:
376 e
= va_arg(args
, chunk_t
);
389 .get_type
= _get_type
,
391 .encrypt
= _encrypt_
,
392 .equals
= public_key_equals
,
393 .get_keysize
= _get_keysize
,
394 .get_fingerprint
= _get_fingerprint
,
395 .has_fingerprint
= public_key_has_fingerprint
,
396 .get_encoding
= _get_encoding
,
404 err
= gcry_sexp_build(&this->key
, NULL
, "(public-key(rsa(n %b)(e %b)))",
405 n
.len
, n
.ptr
, e
.len
, e
.ptr
);
408 DBG1(DBG_LIB
, "loading public key failed: %s", gpg_strerror(err
));
413 return &this->public;