1 /*
2 * Copyright (C) 2021 - This file is part of libecc project
3 *
4 * Authors:
5 * Ryad BENADJILA <ryadbenadjila@gmail.com>
6 * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr>
7 *
8 * This software is licensed under a dual BSD and GPL v2 license.
9 * See LICENSE file at the root folder of the project.
10 */
11 #ifndef __RSA_TESTS_H__
12 #define __RSA_TESTS_H__
13
14 /* Test suite for RSA PKCS#1 algorithms */
15 #include "rsa.h"
16
17 typedef enum {
18 RSA_PKCS1_v1_5_ENC = 0,
19 RSA_PKCS1_v1_5_SIG = 1,
20 RSA_OAEP_ENC = 2,
21 RSA_PSS_SIG = 3,
22 } rsa_alg_type;
23
24 typedef struct {
25 const char *name;
26 rsa_alg_type type;
27 u32 modbits;
28 gen_hash_alg_type hash;
29 const u8 *n;
30 u16 nlen;
31 const u8 *d;
32 u16 dlen;
33 const u8 *e;
34 u16 elen;
35 const u8 *p;
36 u16 plen;
37 const u8 *q;
38 u16 qlen;
39 const u8 *dP;
40 u16 dPlen;
41 const u8 *dQ;
42 u16 dQlen;
43 const u8 *qInv;
44 u16 qInvlen;
45 const u8 *m;
46 u32 mlen;
47 const u8 *res;
48 u32 reslen;
49 const u8 *salt;
50 u32 saltlen;
51 } rsa_test;
52
53
perform_rsa_tests(const rsa_test ** tests,u32 num_tests)54 ATTRIBUTE_WARN_UNUSED_RET static inline int perform_rsa_tests(const rsa_test **tests, u32 num_tests)
55 {
56 int ret = 0, cmp;
57 unsigned int i;
58
59 for(i = 0; i < num_tests; i++){
60 const rsa_test *t = tests[i];
61 u32 modbits = t->modbits;
62 rsa_pub_key pub;
63 rsa_priv_key priv;
64 rsa_priv_key priv_pq;
65
66 /* Import the keys */
67 ret = rsa_import_pub_key(&pub, t->n, (u16)t->nlen, t->e, (u16)t->elen); EG(ret, err1);
68 if(t->dP == NULL){
69 const rsa_test *t_ = NULL;
70 MUST_HAVE((num_tests > 1) && (i < (num_tests - 1)), ret, err);
71 /* NOTE: we use the "next" CRT test to extract p and q */
72 t_ = tests[i + 1];
73 MUST_HAVE((t_->dP != NULL), ret, err);
74 /* Import the RSA_SIMPLE private key with only d and n */
75 ret = rsa_import_simple_priv_key(&priv, t->n, (u16)t->nlen, t->d, (u16)t->dlen, NULL, 0, NULL, 0); EG(ret, err1);
76 /* Import the RSA_SIMPLE_PQ with d, n, p and q */
77 ret = rsa_import_simple_priv_key(&priv_pq, t->n, (u16)t->nlen, t->d, (u16)t->dlen, t_->p, (u16)t_->plen, t_->q, (u16)t_->qlen); EG(ret, err1);
78 }
79 else{
80 /* Import the RSA_CRT CRT key */
81 ret = rsa_import_crt_priv_key(&priv, t->p, (u16)t->plen, t->q, (u16)t->qlen, t->dP, (u16)t->dPlen, t->dQ, (u16)t->dQlen, t->qInv, (u16)t->qInvlen, NULL, NULL, 0); EG(ret, err1);
82 }
83 #ifdef USE_SIG_BLINDING
84 /* We using exponent blinding, only RSA_SIMPLE_PQ are usable. We hence overwrite the key */
85 ret = local_memcpy(&priv, &priv_pq, sizeof(rsa_priv_key)); EG(ret, err);
86 #endif
87 /* Perform our operation */
88 switch(t->type){
89 case RSA_PKCS1_v1_5_ENC:{
90 u8 cipher[NN_USABLE_MAX_BYTE_LEN];
91 u32 clen;
92 if(t->salt != NULL){
93 clen = sizeof(cipher);
94 ret = rsaes_pkcs1_v1_5_encrypt(&pub, t->m, t->mlen, cipher, &clen, modbits, t->salt, t->saltlen); EG(ret, err1);
95 /* Check the result */
96 MUST_HAVE((clen == t->reslen), ret, err1);
97 ret = are_equal(t->res, cipher, t->reslen, &cmp); EG(ret, err1);
98 MUST_HAVE(cmp, ret, err1);
99 }
100 /* Try to decrypt */
101 clen = sizeof(cipher);
102 ret = rsaes_pkcs1_v1_5_decrypt(&priv, t->res, t->reslen, cipher, &clen, modbits); EG(ret, err1);
103 /* Check the result */
104 MUST_HAVE((clen == t->mlen), ret, err1);
105 ret = are_equal(t->m, cipher, t->mlen, &cmp); EG(ret, err1);
106 MUST_HAVE(cmp, ret, err1);
107 /* Try to decrypt with the hardened version */
108 clen = sizeof(cipher);
109 ret = rsaes_pkcs1_v1_5_decrypt_hardened(&priv, &pub, t->res, t->reslen, cipher, &clen, modbits); EG(ret, err1);
110 /* Check the result */
111 MUST_HAVE((clen == t->mlen), ret, err1);
112 ret = are_equal(t->m, cipher, t->mlen, &cmp); EG(ret, err1);
113 MUST_HAVE(cmp, ret, err1);
114 break;
115 }
116 case RSA_OAEP_ENC:{
117 u8 cipher[NN_USABLE_MAX_BYTE_LEN];
118 u32 clen;
119 if(t->salt != NULL){
120 clen = sizeof(cipher);
121 ret = rsaes_oaep_encrypt(&pub, t->m, t->mlen, cipher, &clen, modbits, NULL, 0, t->hash, t->hash, t->salt, t->saltlen); EG(ret, err1);
122 /* Check the result */
123 MUST_HAVE((clen == t->reslen), ret, err1);
124 ret = are_equal(t->res, cipher, t->reslen, &cmp); EG(ret, err1);
125 MUST_HAVE(cmp, ret, err1);
126 }
127 /* Try to decrypt */
128 clen = sizeof(cipher);
129 ret = rsaes_oaep_decrypt(&priv, t->res, t->reslen, cipher, &clen, modbits, NULL, 0, t->hash, t->hash); EG(ret, err1);
130 /* Check the result */
131 MUST_HAVE((clen == t->mlen), ret, err1);
132 ret = are_equal(t->m, cipher, t->mlen, &cmp); EG(ret, err1);
133 MUST_HAVE(cmp, ret, err1);
134 /* Try to decrypt with the hardened version */
135 clen = sizeof(cipher);
136 ret = rsaes_oaep_decrypt_hardened(&priv, &pub, t->res, t->reslen, cipher, &clen, modbits, NULL, 0, t->hash, t->hash); EG(ret, err1);
137 /* Check the result */
138 MUST_HAVE((clen == t->mlen), ret, err1);
139 ret = are_equal(t->m, cipher, t->mlen, &cmp); EG(ret, err1);
140 MUST_HAVE(cmp, ret, err1);
141 break;
142 }
143 case RSA_PKCS1_v1_5_SIG:{
144 u8 sig[NN_USABLE_MAX_BYTE_LEN];
145 u16 siglen = sizeof(sig);
146 MUST_HAVE((t->reslen) <= 0xffff, ret, err1);
147 ret = rsassa_pkcs1_v1_5_verify(&pub, t->m, t->mlen, t->res, (u16)(t->reslen), modbits, t->hash); EG(ret, err1);
148 /* Try to sign */
149 ret = rsassa_pkcs1_v1_5_sign(&priv, t->m, t->mlen, sig, &siglen, modbits, t->hash); EG(ret, err1);
150 /* Check the result */
151 MUST_HAVE((siglen == t->reslen), ret, err1);
152 ret = are_equal(t->res, sig, t->reslen, &cmp); EG(ret, err1);
153 MUST_HAVE(cmp, ret, err1);
154 /* Try to sign with the hardened version */
155 ret = rsassa_pkcs1_v1_5_sign_hardened(&priv, &pub, t->m, t->mlen, sig, &siglen, modbits, t->hash); EG(ret, err1);
156 /* Check the result */
157 MUST_HAVE((siglen == t->reslen), ret, err1);
158 ret = are_equal(t->res, sig, t->reslen, &cmp); EG(ret, err1);
159 MUST_HAVE(cmp, ret, err1);
160 break;
161 }
162 case RSA_PSS_SIG:{
163 if(t->salt == NULL){
164 /* In case of NULL salt, default saltlen value is the digest size */
165 u8 digestsize, blocksize;
166 ret = gen_hash_get_hash_sizes(t->hash, &digestsize, &blocksize); EG(ret, err1);
167 MUST_HAVE((t->reslen) <= 0xffff, ret, err1);
168 ret = rsassa_pss_verify(&pub, t->m, t->mlen, t->res, (u16)(t->reslen), modbits, t->hash, t->hash, digestsize); EG(ret, err1);
169 }
170 else{
171 MUST_HAVE((t->reslen) <= 0xffff, ret, err1);
172 ret = rsassa_pss_verify(&pub, t->m, t->mlen, t->res, (u16)(t->reslen), modbits, t->hash, t->hash, t->saltlen); EG(ret, err1);
173 }
174 if(t->salt != NULL){
175 /* Try to sign */
176 u8 sig[NN_USABLE_MAX_BYTE_LEN];
177 u16 siglen = sizeof(sig);
178 ret = rsassa_pss_sign(&priv, t->m, t->mlen, sig, &siglen, modbits, t->hash, t->hash, t->saltlen, t->salt); EG(ret, err1);
179 /* Check the result */
180 MUST_HAVE((t->reslen) <= 0xffff, ret, err1);
181 MUST_HAVE((siglen == (u16)(t->reslen)), ret, err1);
182 ret = are_equal(t->res, sig, t->reslen, &cmp); EG(ret, err1);
183 MUST_HAVE(cmp, ret, err1);
184 /* Try to sign with the hardened version */
185 ret = rsassa_pss_sign_hardened(&priv, &pub, t->m, t->mlen, sig, &siglen, modbits, t->hash, t->hash, t->saltlen, t->salt); EG(ret, err1);
186 /* Check the result */
187 MUST_HAVE((siglen == (u16)(t->reslen)), ret, err1);
188 ret = are_equal(t->res, sig, t->reslen, &cmp); EG(ret, err1);
189 MUST_HAVE(cmp, ret, err1);
190 }
191 break;
192 }
193 default:{
194 ret = -1;
195 break;
196 }
197 }
198 err1:
199 if(ret){
200 ext_printf("[-] Test %s failed (modbits = %" PRIu32 ")\n", t->name, t->modbits);
201 goto err;
202 }
203 else{
204 ext_printf("[+] Test %s passed (modbits = %" PRIu32 ")\n", t->name, t->modbits);
205 }
206 }
207
208 if(!ret){
209 ext_printf("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\t=== [+] All RSA tests went OK! ===\n");
210 }
211 err:
212 return ret;
213 }
214
215 #endif /* __RSA_TESTS_H__ */
216