Skip to content

Commit 6c751f5

Browse files
committed
Add support for RSA-PSS keys
Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
1 parent a0478cc commit 6c751f5

15 files changed

+473
-147
lines changed

src/headers/tomcrypt_pk.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ enum ltc_pka_id {
4040
LTC_PKA_X25519,
4141
LTC_PKA_ED25519,
4242
LTC_PKA_DH,
43+
LTC_PKA_RSA_PSS,
4344
LTC_PKA_NUM
4445
};
4546

@@ -62,7 +63,18 @@ int rand_prime(void *N, long len, prng_state *prng, int wprng);
6263
/* ---- RSA ---- */
6364
#ifdef LTC_MRSA
6465

65-
/** RSA PKCS style key */
66+
typedef struct ltc_rsa_parameters {
67+
/** PSS/OAEP or PKCS #1 v1.5 style
68+
* 0 -> PKCS #1 v1.5, 1 -> PSS/OAEP */
69+
int pss_oaep;
70+
/** saltLength is only defined for PSS
71+
* If saltLength == 0 -> OAEP, else -> PSS */
72+
unsigned long saltlen;
73+
/** hash and MGF hash algorithms */
74+
const char *hash_alg, *mgf1_hash_alg;
75+
} ltc_rsa_parameters;
76+
77+
/** RSA key */
6678
typedef struct Rsa_key {
6779
/** Type of key, PK_PRIVATE or PK_PUBLIC */
6880
int type;
@@ -82,6 +94,8 @@ typedef struct Rsa_key {
8294
void *dP;
8395
/** The d mod (q - 1) CRT param */
8496
void *dQ;
97+
/** Further parameters of the RSA key */
98+
ltc_rsa_parameters params;
8599
} rsa_key;
86100

87101
int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key);
@@ -1029,7 +1043,11 @@ typedef struct ltc_x509_time {
10291043

10301044
typedef struct ltc_x509_signature_algorithm {
10311045
enum ltc_pka_id pka;
1032-
const char *hash;
1046+
union {
1047+
const char *hash;
1048+
ltc_rsa_parameters rsa_params;
1049+
} u;
1050+
const ltc_asn1_list *asn1;
10331051
} ltc_x509_signature_algorithm;
10341052

10351053
typedef struct ltc_x509_validity {

src/headers/tomcrypt_private.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ enum ltc_oid_id {
6060
LTC_OID_X25519,
6161
LTC_OID_ED25519,
6262
LTC_OID_DH,
63+
LTC_OID_RSA_OAEP,
64+
LTC_OID_RSA_MGF1,
65+
LTC_OID_RSA_PSS,
6366
LTC_OID_RSA_WITH_MD5,
6467
LTC_OID_RSA_WITH_SHA1,
6568
LTC_OID_RSA_WITH_SHA224,
@@ -439,8 +442,14 @@ int pk_oid_cmp_with_ulong(const char *o1, const unsigned long *o2, unsigned long
439442

440443
/* ---- DH Routines ---- */
441444
#ifdef LTC_MRSA
445+
typedef enum ltc_rsa_op {
446+
LTC_RSA_CRYPT,
447+
LTC_RSA_SIGN
448+
} ltc_rsa_op;
442449
int rsa_init(rsa_key *key);
443450
void rsa_shrink_key(rsa_key *key);
451+
int rsa_key_valid_op(const rsa_key *key, ltc_rsa_op op, int padding, int hash_idx);
452+
int rsa_params_equal(const ltc_rsa_parameters *a, const ltc_rsa_parameters *b);
444453
int rsa_make_key_bn_e(prng_state *prng, int wprng, int size, void *e,
445454
rsa_key *key); /* used by op-tee */
446455
int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key);
@@ -680,7 +689,11 @@ int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned lo
680689
enum ltc_oid_id algorithm, ltc_asn1_type param_type,
681690
ltc_asn1_list* parameters, unsigned long *parameters_len,
682691
public_key_decode_cb callback, void *ctx);
683-
int x509_decode_spki(const unsigned char *in, unsigned long inlen, ltc_asn1_list **out, ltc_asn1_list **spki);
692+
int x509_decode_spki(const unsigned char *in, unsigned long inlen, ltc_asn1_list **out, const ltc_asn1_list **spki);
693+
int x509_process_public_key_from_spki(const unsigned char *in, unsigned long inlen,
694+
enum ltc_oid_id algorithm, ltc_asn1_type param_type,
695+
ltc_asn1_list* parameters, unsigned long *parameters_len,
696+
public_key_decode_cb callback, void *ctx);
684697

685698
/* SUBJECT PUBLIC KEY INFO */
686699
int x509_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen,

src/pk/asn1/oid/pk_get.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ static const oid_table_entry pka_oids[] = {
2020
{ LTC_OID_X25519, LTC_PKA_X25519, NULL, "1.3.101.110" },
2121
{ LTC_OID_ED25519, LTC_PKA_ED25519, NULL, "1.3.101.112" },
2222
{ LTC_OID_DH, LTC_PKA_DH, NULL, "1.2.840.113549.1.3.1" },
23+
{ LTC_OID_RSA_OAEP, LTC_PKA_RSA, NULL, "1.2.840.113549.1.1.7" },
24+
{ LTC_OID_RSA_MGF1, LTC_PKA_RSA, NULL, "1.2.840.113549.1.1.8" },
25+
{ LTC_OID_RSA_PSS, LTC_PKA_RSA_PSS, NULL, "1.2.840.113549.1.1.10" },
2326
{ LTC_OID_RSA_WITH_MD5, LTC_PKA_RSA, "md5", "1.2.840.113549.1.1.4" },
2427
{ LTC_OID_RSA_WITH_SHA1, LTC_PKA_RSA, "sha1", "1.2.840.113549.1.1.5" },
2528
{ LTC_OID_RSA_WITH_SHA224, LTC_PKA_RSA, "sha224", "1.2.840.113549.1.1.14" },
@@ -106,7 +109,7 @@ int pk_get_pka_id(enum ltc_oid_id id, enum ltc_pka_id *pka)
106109
int pk_get_sig_alg(enum ltc_oid_id id, ltc_x509_signature_algorithm *sig_alg)
107110
{
108111
LTC_ARGCHK(sig_alg != NULL);
109-
return s_get_values(id, &sig_alg->pka, &sig_alg->hash);
112+
return s_get_values(id, &sig_alg->pka, &sig_alg->u.hash);
110113
}
111114

112115
/*

src/pk/asn1/x509/x509_decode_public_key_from_certificate.c

Lines changed: 52 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#ifdef LTC_DER
1111

1212
/**
13-
Try to decode the public key from a X.509 certificate
13+
Process the public key from the SubjectPublicKeyInfo of a X.509 certificate
1414
@param in The input buffer
1515
@param inlen The length of the input buffer
1616
@param algorithm One out of the enum #public_key_algorithms
@@ -19,53 +19,82 @@
1919
@param parameters_len [in/out] The number of parameters to include
2020
@param callback The callback
2121
@param ctx The context passed to the callback
22-
@return CRYPT_OK on success,
23-
CRYPT_NOP if no SubjectPublicKeyInfo was found,
24-
another error if decoding or memory allocation failed
22+
@return CRYPT_OK on success
2523
*/
26-
int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned long inlen,
27-
enum ltc_oid_id algorithm, ltc_asn1_type param_type,
28-
ltc_asn1_list* parameters, unsigned long *parameters_len,
29-
public_key_decode_cb callback, void *ctx)
24+
int x509_process_public_key_from_spki(const unsigned char *in, unsigned long inlen,
25+
enum ltc_oid_id algorithm, ltc_asn1_type param_type,
26+
ltc_asn1_list* parameters, unsigned long *parameters_len,
27+
public_key_decode_cb callback, void *ctx)
3028
{
3129
int err;
3230
unsigned char *tmpbuf = NULL;
3331
unsigned long tmpbuf_len;
34-
ltc_asn1_list *decoded_list = NULL, *spki;
35-
36-
LTC_ARGCHK(in != NULL);
37-
LTC_ARGCHK(inlen != 0);
38-
LTC_ARGCHK(callback != NULL);
3932

40-
if ((err = x509_decode_spki(in, inlen, &decoded_list, &spki)) != CRYPT_OK) {
41-
return err;
42-
}
33+
LTC_ARGCHK(in != NULL);
34+
LTC_ARGCHK(callback != NULL);
4335

4436
if (algorithm == LTC_OID_EC) {
45-
err = callback(spki->data, spki->size, ctx);
37+
err = callback(in, inlen, ctx);
4638
} else {
4739

4840
tmpbuf_len = inlen;
4941
tmpbuf = XCALLOC(1, tmpbuf_len);
5042
if (tmpbuf == NULL) {
51-
err = CRYPT_MEM;
52-
goto LBL_OUT;
43+
return CRYPT_MEM;
5344
}
5445

55-
err = x509_decode_subject_public_key_info(spki->data, spki->size,
46+
err = x509_decode_subject_public_key_info(in, inlen,
5647
algorithm, tmpbuf, &tmpbuf_len,
5748
param_type, parameters, parameters_len);
5849
if (err == CRYPT_OK) {
5950
err = callback(tmpbuf, tmpbuf_len, ctx);
60-
goto LBL_OUT;
6151
}
6252
}
6353

64-
LBL_OUT:
65-
if (decoded_list) der_free_sequence_flexi(decoded_list);
6654
if (tmpbuf != NULL) XFREE(tmpbuf);
6755

6856
return err;
6957
}
7058

59+
/**
60+
Try to decode the public key from a X.509 certificate
61+
@param in The input buffer
62+
@param inlen The length of the input buffer
63+
@param algorithm One out of the enum #public_key_algorithms
64+
@param param_type The parameters' type out of the enum ltc_asn1_type
65+
@param parameters The parameters to include
66+
@param parameters_len [in/out] The number of parameters to include
67+
@param callback The callback
68+
@param ctx The context passed to the callback
69+
@return CRYPT_OK on success,
70+
CRYPT_NOP if no SubjectPublicKeyInfo was found,
71+
another error if decoding or memory allocation failed
72+
*/
73+
int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned long inlen,
74+
enum ltc_oid_id algorithm, ltc_asn1_type param_type,
75+
ltc_asn1_list* parameters, unsigned long *parameters_len,
76+
public_key_decode_cb callback, void *ctx)
77+
{
78+
int err;
79+
ltc_asn1_list *decoded_list;
80+
const ltc_asn1_list *spki;
81+
82+
LTC_ARGCHK(in != NULL);
83+
LTC_ARGCHK(inlen != 0);
84+
LTC_ARGCHK(callback != NULL);
85+
86+
if ((err = x509_decode_spki(in, inlen, &decoded_list, &spki)) != CRYPT_OK) {
87+
return err;
88+
}
89+
90+
err = x509_process_public_key_from_spki(spki->data, spki->size,
91+
algorithm, param_type,
92+
parameters, parameters_len,
93+
callback, ctx);
94+
95+
if (decoded_list) der_free_sequence_flexi(decoded_list);
96+
97+
return err;
98+
}
99+
71100
#endif

src/pk/asn1/x509/x509_decode_spki.c

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@
2626
@param spki [out] A pointer to the SubjectPublicKeyInfo
2727
@return CRYPT_OK on success, CRYPT_NOP if no SubjectPublicKeyInfo was found, another error if decoding failed
2828
*/
29-
int x509_decode_spki(const unsigned char *in, unsigned long inlen, ltc_asn1_list **out, ltc_asn1_list **spki)
29+
int x509_decode_spki(const unsigned char *in, unsigned long inlen, ltc_asn1_list **out, const ltc_asn1_list **spki)
3030
{
3131
int err;
32-
unsigned long tmp_inlen;
32+
unsigned long tmp_inlen, n, element_is_spki;
3333
ltc_asn1_list *decoded_list = NULL, *l;
3434

3535
LTC_ARGCHK(in != NULL);
@@ -49,29 +49,49 @@ int x509_decode_spki(const unsigned char *in, unsigned long inlen, ltc_asn1_list
4949
if ((l->type == LTC_ASN1_SEQUENCE) && (l->child != NULL)) {
5050
l = l->child;
5151
if ((l->type == LTC_ASN1_SEQUENCE) && (l->child != NULL)) {
52+
/* TBSCertificate ::= SEQUENCE {
53+
* version [0] EXPLICIT Version DEFAULT v1,
54+
* serialNumber CertificateSerialNumber,
55+
* signature AlgorithmIdentifier,
56+
* issuer Name,
57+
* validity Validity,
58+
* subject Name,
59+
* subjectPublicKeyInfo SubjectPublicKeyInfo,
60+
* issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
61+
* -- If present, version MUST be v2 or v3
62+
* subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
63+
* -- If present, version MUST be v2 or v3
64+
* extensions [3] EXPLICIT Extensions OPTIONAL
65+
* -- If present, version MUST be v3
66+
* }
67+
*/
5268
l = l->child;
5369

54-
/* Move forward in the tree until we find this combination
55-
...
56-
SEQUENCE
57-
SEQUENCE
58-
OBJECT IDENTIFIER <some PKA OID, e.g. 1.2.840.113549.1.1.1>
59-
NULL
60-
BIT STRING
70+
/* `l` points now either to 'version' or 'serialNumber', depending on
71+
* whether 'version' is included or defaults to 'v1'.
72+
* 'version' is represented as a LTC_ASN1_CUSTOM_TYPE
73+
* 'serialNumber' is represented as an LTC_ASN1_INTEGER
74+
* Decide now whether to move 5 or 6 elements forward until
75+
* `l` should point to subjectPublicKeyInfo.
6176
*/
62-
do {
63-
/* The additional check for l->data is there to make sure
64-
* we won't try to decode a list that has been 'shrunk'
65-
*/
66-
if ((l->type == LTC_ASN1_SEQUENCE)
67-
&& (l->data != NULL)
68-
&& LOOKS_LIKE_SPKI(l->child)) {
69-
*out = decoded_list;
70-
*spki = l;
71-
return CRYPT_OK;
72-
}
77+
if (l->type == LTC_ASN1_CUSTOM_TYPE)
78+
element_is_spki = 6;
79+
else
80+
element_is_spki = 5;
81+
for (n = 0; n < element_is_spki && l; ++n) {
7382
l = l->next;
74-
} while(l);
83+
}
84+
/* The additional check for l->data is there to make sure
85+
* we won't try to decode a list that has been 'shrunk'
86+
*/
87+
if ((l != NULL)
88+
&& (l->type == LTC_ASN1_SEQUENCE)
89+
&& (l->data != NULL)
90+
&& LOOKS_LIKE_SPKI(l->child)) {
91+
*out = decoded_list;
92+
*spki = l;
93+
return CRYPT_OK;
94+
}
7595
}
7696
}
7797
}

src/pk/asn1/x509/x509_import_spki.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ typedef int (*import_fn)(const unsigned char *, unsigned long, void*);
1414
static const import_fn s_import_x509_fns[LTC_PKA_NUM] = {
1515
#ifdef LTC_MRSA
1616
[LTC_PKA_RSA] = (import_fn)rsa_import_x509,
17+
[LTC_PKA_RSA_PSS] = (import_fn)rsa_import_x509,
1718
#endif
1819
#ifdef LTC_MDSA
1920
[LTC_PKA_DSA] = (import_fn)dsa_import,
@@ -30,7 +31,8 @@ static const import_fn s_import_x509_fns[LTC_PKA_NUM] = {
3031
int x509_import_spki(const unsigned char *asn1_cert, unsigned long asn1_len, ltc_pka_key *k, ltc_asn1_list **root)
3132
{
3233
enum ltc_pka_id pka = LTC_PKA_UNDEF;
33-
ltc_asn1_list *d, *spki;
34+
ltc_asn1_list *d;
35+
const ltc_asn1_list *spki;
3436
int err;
3537
if ((err = x509_decode_spki(asn1_cert, asn1_len, &d, &spki)) != CRYPT_OK) {
3638
return err;

0 commit comments

Comments
 (0)