25 #include "exceptions.h"
37 #if defined(HAVE_SHA224)
39 const uint8_t C_cx_oid_sha224[CX_OID_SHA224_LENGTH] = {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
40 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c};
43 #if defined(HAVE_SHA256)
45 const uint8_t C_cx_oid_sha256[CX_OID_SHA256_LENGTH] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
46 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
49 #if defined(HAVE_SHA384)
51 const uint8_t C_cx_oid_sha384[CX_OID_SHA384_LENGTH] = {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
52 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30};
55 #if defined(HAVE_SHA512)
57 const uint8_t C_cx_oid_sha512[CX_OID_SHA512_LENGTH] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
58 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
61 #if defined(HAVE_SHA3)
63 const uint8_t C_cx_oid_sha3_256[CX_OID_SHA3_256_LENGTH]
64 = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
65 0x65, 0x03, 0x04, 0x02, 0x08, 0x05, 0x00, 0x04, 0x20};
68 const uint8_t C_cx_oid_sha3_512[CX_OID_SHA3_512_LENGTH]
69 = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
70 0x65, 0x03, 0x04, 0x02, 0x0a, 0x05, 0x00, 0x04, 0x40};
74 size_t cx_pkcs1_get_hash_len(cx_md_t hID)
77 #if defined(HAVE_SHA224)
82 #if defined(HAVE_SHA256)
87 #if defined(HAVE_SHA384)
92 #if defined(HAVE_SHA512)
97 #if defined(HAVE_SHA3)
111 static const uint8_t *cx_pkcs1_get_hash_oid(cx_md_t hID,
size_t *len)
114 #if defined(HAVE_SHA224)
116 *len =
sizeof(C_cx_oid_sha224);
117 return C_cx_oid_sha224;
120 #if defined(HAVE_SHA256)
122 *len =
sizeof(C_cx_oid_sha256);
123 return C_cx_oid_sha256;
126 #if defined(HAVE_SHA384)
128 *len =
sizeof(C_cx_oid_sha384);
129 return C_cx_oid_sha384;
132 #if defined(HAVE_SHA512)
134 *len =
sizeof(C_cx_oid_sha512);
135 return C_cx_oid_sha512;
138 #if defined(HAVE_SHA3)
140 *len =
sizeof(C_cx_oid_sha3_256);
141 return C_cx_oid_sha3_256;
144 *len =
sizeof(C_cx_oid_sha3_512);
145 return C_cx_oid_sha3_512;
155 #ifdef _CX_PKCS1_CONST_SEED_SALT
156 static const uint8_t C_cx_pkcs_salt[]
157 = {
'T',
'h',
'e',
'S',
'a',
'l',
't',
' ',
'T',
'h',
'e',
'S',
'a',
'l',
't',
' ',
158 'T',
'h',
'e',
'S',
'a',
'l',
't',
' ',
'T',
'h',
'e',
'S',
'a',
'l',
't',
' '};
161 static const uint8_t C_cx_pss_zeros[] = {0, 0, 0, 0, 0, 0, 0, 0};
165 #if defined(HAVE_SHA224)
166 static const uint8_t C_cx_oeap_sha224_[]
167 = {0xd1, 0x4a, 0x02, 0x8c, 0x2a, 0x3a, 0x2b, 0xc9, 0x47, 0x61, 0x02, 0xbb, 0x28, 0x82,
168 0x34, 0xc4, 0x15, 0xa2, 0xb0, 0x1f, 0x82, 0x8e, 0xa6, 0x2a, 0xc5, 0xb3, 0xe4, 0x2f};
171 #if defined(HAVE_SHA256)
172 static const uint8_t C_cx_oeap_sha256_[] = {
173 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
174 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
178 #if defined(HAVE_SHA384)
179 static const uint8_t C_cx_oeap_sha384_[] = {
180 0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a,
181 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda,
182 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b};
185 #if defined(HAVE_SHA512)
186 static const uint8_t C_cx_oeap_sha512_[] = {
187 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
188 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc, 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
189 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0, 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
190 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81, 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e};
193 static const uint8_t *cx_pkcs1_get_hash_oeap(cx_md_t hID,
size_t *len)
196 #if defined(HAVE_SHA224)
198 *len =
sizeof(C_cx_oeap_sha224_);
199 return C_cx_oeap_sha224_;
202 #if defined(HAVE_SHA256)
204 *len =
sizeof(C_cx_oeap_sha256_);
205 return C_cx_oeap_sha256_;
208 #if defined(HAVE_SHA384)
210 *len =
sizeof(C_cx_oeap_sha384_);
211 return C_cx_oeap_sha384_;
214 #if defined(HAVE_SHA512)
216 *len =
sizeof(C_cx_oeap_sha512_);
217 return C_cx_oeap_sha512_;
227 static cx_err_t cx_pkcs1_MGF1(cx_md_t hID,
236 cx_hash_t *hash_ctx = &
G_cx.pkcs1.hash_ctx.hash;
237 cx_err_t error = CX_OK;
239 if (hID != CX_SHA224 && hID != CX_SHA256 && hID != CX_SHA384 && hID != CX_SHA512
240 && hID != CX_SHA3_256 && hID != CX_SHA3_512) {
241 return CX_INVALID_PARAMETER;
243 hLen = cx_pkcs1_get_hash_len(hID);
246 round_len = (out_len < hLen) ? out_len : hLen;
248 CX_CHECK(cx_hash_init_ex(hash_ctx, hID, hLen));
249 CX_CHECK(cx_hash_update(hash_ctx, seed, seed_len));
250 CX_CHECK(cx_hash_update(hash_ctx, counter, 4));
251 CX_CHECK(cx_hash_final(hash_ctx,
G_cx.pkcs1.digest));
253 memcpy(out,
G_cx.pkcs1.digest, round_len);
254 out_len -= round_len;
257 if (counter[3] == 0) {
272 cx_err_t cx_pkcs1_emsa_v1o5_encode(cx_md_t hID,
282 oid = cx_pkcs1_get_hash_oid(hID, &oid_len);
284 return CX_INVALID_PARAMETER;
287 if ((3 + oid_len + mHashLen) >= emLen) {
288 return CX_INVALID_PARAMETER;
290 PSLen = emLen - (3 + oid_len + mHashLen);
292 memcpy(em + 2 + PSLen + 1 + oid_len, mHash, mHashLen);
293 memcpy(em + 2 + PSLen + 1, oid, oid_len);
296 memset(em + 2, 0xFF, PSLen);
307 bool cx_pkcs1_emsa_v1o5_verify(cx_md_t hID,
318 oid = cx_pkcs1_get_hash_oid(hID, &oid_len);
323 if ((3 + oid_len + mHashLen) >= emLen) {
326 PSLen = emLen - (3 + oid_len + mHashLen);
329 if ((em[0]) || (em[1] != 1) || (em[2 + PSLen] != 0)) {
333 for (i = 2 + PSLen - 1; i >= 2; i--) {
339 if (memcmp(em + 2 + PSLen + 1, oid, oid_len) != 0
340 || memcmp(em + 2 + PSLen + 1 + oid_len, mHash, mHashLen) != 0) {
351 static uint8_t const CX_PSS_MASK[] = {0, 0x7F, 0x3F, 0x1F, 0xF, 0x7, 0x3, 0x1};
353 cx_err_t cx_pkcs1_emsa_pss_encode_with_salt_len(cx_md_t hID,
366 cx_hash_t *hash_ctx = &
G_cx.pkcs1.hash_ctx.hash;
369 if (hID != CX_SHA224 && hID != CX_SHA256 && hID != CX_SHA384 && hID != CX_SHA512) {
370 return CX_INVALID_PARAMETER;
373 hLen = cx_pkcs1_get_hash_len(hID);
374 emLen = (emBits + 7) / 8;
376 if ((1 + hLen) >= emLen) {
377 return CX_INVALID_PARAMETER;
379 mDBlen = emLen - (1 + hLen);
381 if ((hLen + mSaltLen + 2) >= emLen) {
382 return CX_INVALID_PARAMETER;
384 PSLen = emLen - (mSaltLen + hLen + 2);
386 #ifndef _CX_PKCS1_CONST_SEED_SALT
387 cx_rng_no_throw(salt, mSaltLen);
390 CX_CHECK(cx_hash_init_ex(hash_ctx, hID, hLen));
391 CX_CHECK(cx_hash_update(hash_ctx, C_cx_pss_zeros, 8));
392 CX_CHECK(cx_hash_update(hash_ctx, mHash, mHashLen));
393 CX_CHECK(cx_hash_update(hash_ctx, salt, mSaltLen));
394 CX_CHECK(cx_hash_final(hash_ctx, em + mDBlen));
396 em[emLen - 1] = 0xbc;
397 CX_CHECK(cx_pkcs1_MGF1(hID, em + mDBlen, hLen, em, mDBlen));
399 cx_memxor(em + PSLen + 1, salt, mSaltLen);
400 em[0] &= CX_PSS_MASK[8 * emLen - emBits];
402 explicit_bzero(&
G_cx.pkcs1,
sizeof(cx_pkcs1_t));
407 cx_err_t cx_pkcs1_emsa_pss_encode(cx_md_t hID,
414 size_t hLen = cx_pkcs1_get_hash_len(hID);
415 return cx_pkcs1_emsa_pss_encode_with_salt_len(hID, em, emBits, mHash, mHashLen, hLen, size);
418 bool cx_pkcs1_emsa_pss_verify_with_salt_len(cx_md_t hID,
430 cx_hash_t *hash_ctx = &
G_cx.pkcs1.hash_ctx.hash;
432 if (hID != CX_SHA224 && hID != CX_SHA256 && hID != CX_SHA384 && hID != CX_SHA512) {
436 hLen = cx_pkcs1_get_hash_len(hID);
437 emLen = (emBits + 7) / 8;
439 if ((1 + hLen) >= emLen) {
442 mDBlen = emLen - (1 + hLen);
444 if ((mSaltLen + hLen + 2) >= emLen) {
447 PSLen = emLen - (mSaltLen + hLen + 2);
449 if (em[emLen - 1] != 0xbc) {
452 if (em[0] & ~CX_PSS_MASK[8 * emLen - emBits]) {
455 if (cx_pkcs1_MGF1(hID, em + mDBlen, hLen,
G_cx.pkcs1.MGF1, mDBlen) != CX_OK) {
459 em[0] &= CX_PSS_MASK[8 * emLen - emBits];
460 for (i = 0; i < PSLen; i++) {
465 if (em[PSLen] != 0x01) {
469 if (cx_hash_init_ex(hash_ctx, hID, hLen) != CX_OK
470 || cx_hash_update(hash_ctx, C_cx_pss_zeros, 8) != CX_OK
471 || cx_hash_update(hash_ctx, mHash, mHashLen) != CX_OK
472 || cx_hash_update(hash_ctx, em + PSLen + 1, mSaltLen) != CX_OK
473 || cx_hash_final(hash_ctx,
G_cx.pkcs1.digest) != CX_OK) {
477 return memcmp(
G_cx.pkcs1.digest, em + mDBlen, hLen) == 0;
480 bool cx_pkcs1_emsa_pss_verify(cx_md_t hID,
490 size_t hLen = cx_pkcs1_get_hash_len(hID);
491 return cx_pkcs1_emsa_pss_verify_with_salt_len(hID, em, emBits, mHash, mHashLen, hLen);
497 cx_err_t cx_pkcs1_eme_v1o5_encode(cx_md_t hID,
507 if ((3 + mLen) >= emLen) {
508 return CX_INVALID_PARAMETER;
510 PSLen = emLen - (3 + mLen);
512 memcpy(em + 2 + PSLen + 1, m, mLen);
515 cx_rng_no_throw(em + 2, PSLen);
516 for (offset = 2 + PSLen - 1; offset >= 2; offset--) {
517 if (em[offset] == 0) {
525 size_t cx_pkcs1_eme_v1o5_decode(cx_md_t hID,
uint8_t *em,
size_t emLen,
uint8_t *m,
size_t mLen)
530 if ((em[0]) || (em[1] != 2)) {
535 while (offset < emLen) {
536 if (em[offset] == 0) {
541 if (offset == emLen) {
546 if (mLen < emLen - offset) {
549 mLen = emLen - offset;
550 memmove(m, em + offset, mLen);
557 cx_err_t cx_pkcs1_eme_oaep_encode(cx_md_t hID,
572 hLen = cx_pkcs1_get_hash_len(hID);
573 lHash = cx_pkcs1_get_hash_oeap(hID, &lHashLen);
574 if (hLen == 0 || lHash == NULL) {
575 return CX_INVALID_PARAMETER;
578 if ((hLen + 1) >= emLen) {
579 return CX_INVALID_PARAMETER;
581 mDBlen = emLen - (hLen + 1);
582 if ((mLen + 2 * hLen + 2) >= emLen) {
583 return CX_INVALID_PARAMETER;
585 psLen = emLen - (mLen + 2 * hLen + 2);
588 cx_rng_no_throw(seed, hLen);
592 memcpy(em + offset, lHash, lHashLen);
594 memset(em + offset, 0, psLen);
598 memcpy(em + offset, m, mLen);
603 CX_CHECK(cx_pkcs1_MGF1(hID, seed, hLen,
G_cx.pkcs1.MGF1, mDBlen));
606 CX_CHECK(cx_pkcs1_MGF1(hID, em + 1 + hLen, mDBlen,
G_cx.pkcs1.MGF1, hLen));
607 memcpy(em + 1, seed, hLen);
614 cx_err_t cx_pkcs1_eme_oaep_decode(cx_md_t hID,
uint8_t *em,
size_t emLen,
uint8_t *m,
size_t *mLen)
623 hLen = cx_pkcs1_get_hash_len(hID);
624 lHash = cx_pkcs1_get_hash_oeap(hID, &lHashLen);
625 if (hLen == 0 || lHash == NULL) {
626 return CX_INVALID_PARAMETER;
628 if ((hLen + 1) >= emLen) {
629 return CX_INVALID_PARAMETER;
631 mDBlen = emLen - (hLen + 1);
634 CX_CHECK(cx_pkcs1_MGF1(hID, em + 1 + hLen, mDBlen,
G_cx.pkcs1.MGF1, hLen));
636 CX_CHECK(cx_pkcs1_MGF1(hID, em + 1, hLen,
G_cx.pkcs1.MGF1, mDBlen));
641 return CX_INVALID_PARAMETER;
643 if (memcmp(em + 1 + hLen, lHash, hLen) != 0) {
644 return CX_INVALID_PARAMETER;
647 for (offset = 1 + hLen + lHashLen; offset < emLen; offset++) {
648 if (em[offset] != 0) {
652 if ((offset == emLen) || (em[offset] != 0x01)) {
653 return CX_INVALID_PARAMETER;
658 if (*mLen < emLen - offset) {
659 return CX_INVALID_PARAMETER;
662 *mLen = emLen - offset;
663 memmove(m, em + offset, *mLen);
void cx_memxor(uint8_t *buf1, const uint8_t *buf2, size_t len)
Random Number Generation.