25#include "exceptions.h"
37#if defined(HAVE_SHA224)
39const 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)
45const 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)
51const 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)
57const 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};
63const 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};
68const 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};
74size_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)
111static 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
156static 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',
' '};
161static const uint8_t C_cx_pss_zeros[] = {0, 0, 0, 0, 0, 0, 0, 0};
165#if defined(HAVE_SHA224)
166static 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)
172static 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)
179static 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)
186static 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};
193static 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_;
227static cx_err_t cx_pkcs1_MGF1(cx_md_t hID,
235 uint8_t counter[4] = {0};
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) {
272cx_err_t cx_pkcs1_emsa_v1o5_encode(cx_md_t hID,
275 const uint8_t *mHash,
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);
307bool cx_pkcs1_emsa_v1o5_verify(cx_md_t hID,
310 const uint8_t *mHash,
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) {
351static uint8_t
const CX_PSS_MASK[] = {0, 0x7F, 0x3F, 0x1F, 0xF, 0x7, 0x3, 0x1};
353cx_err_t cx_pkcs1_emsa_pss_encode_with_salt_len(cx_md_t hID,
356 const uint8_t *mHash,
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 (mSaltLen >
sizeof(salt)) {
382 return CX_INVALID_PARAMETER;
384 if ((hLen + mSaltLen + 2) >= emLen) {
385 return CX_INVALID_PARAMETER;
387 PSLen = emLen - (mSaltLen + hLen + 2);
389#ifndef _CX_PKCS1_CONST_SEED_SALT
390 cx_rng_no_throw(salt, mSaltLen);
393 CX_CHECK(cx_hash_init_ex(hash_ctx, hID, hLen));
394 CX_CHECK(cx_hash_update(hash_ctx, C_cx_pss_zeros, 8));
395 CX_CHECK(cx_hash_update(hash_ctx, mHash, mHashLen));
396 CX_CHECK(cx_hash_update(hash_ctx, salt, mSaltLen));
397 CX_CHECK(cx_hash_final(hash_ctx, em + mDBlen));
399 em[emLen - 1] = 0xbc;
400 CX_CHECK(cx_pkcs1_MGF1(hID, em + mDBlen, hLen, em, mDBlen));
402 cx_memxor(em + PSLen + 1, salt, mSaltLen);
403 em[0] &= CX_PSS_MASK[8 * emLen - emBits];
405 explicit_bzero(&
G_cx.pkcs1,
sizeof(cx_pkcs1_t));
410cx_err_t cx_pkcs1_emsa_pss_encode(cx_md_t hID,
413 const uint8_t *mHash,
417 size_t hLen = cx_pkcs1_get_hash_len(hID);
418 return cx_pkcs1_emsa_pss_encode_with_salt_len(hID, em, emBits, mHash, mHashLen, hLen, size);
421bool cx_pkcs1_emsa_pss_verify_with_salt_len(cx_md_t hID,
424 const uint8_t *mHash,
433 cx_hash_t *hash_ctx = &
G_cx.pkcs1.hash_ctx.hash;
435 if (hID != CX_SHA224 && hID != CX_SHA256 && hID != CX_SHA384 && hID != CX_SHA512) {
439 hLen = cx_pkcs1_get_hash_len(hID);
440 emLen = (emBits + 7) / 8;
442 if ((1 + hLen) >= emLen) {
445 mDBlen = emLen - (1 + hLen);
447 if ((mSaltLen + hLen + 2) >= emLen) {
450 PSLen = emLen - (mSaltLen + hLen + 2);
452 if (em[emLen - 1] != 0xbc) {
455 if (em[0] & ~CX_PSS_MASK[8 * emLen - emBits]) {
458 if (cx_pkcs1_MGF1(hID, em + mDBlen, hLen,
G_cx.pkcs1.MGF1, mDBlen) != CX_OK) {
462 em[0] &= CX_PSS_MASK[8 * emLen - emBits];
463 for (i = 0; i < PSLen; i++) {
468 if (em[PSLen] != 0x01) {
472 if (cx_hash_init_ex(hash_ctx, hID, hLen) != CX_OK
473 || cx_hash_update(hash_ctx, C_cx_pss_zeros, 8) != CX_OK
474 || cx_hash_update(hash_ctx, mHash, mHashLen) != CX_OK
475 || cx_hash_update(hash_ctx, em + PSLen + 1, mSaltLen) != CX_OK
476 || cx_hash_final(hash_ctx,
G_cx.pkcs1.digest) != CX_OK) {
480 return memcmp(
G_cx.pkcs1.digest, em + mDBlen, hLen) == 0;
483bool cx_pkcs1_emsa_pss_verify(cx_md_t hID,
486 const uint8_t *mHash,
493 size_t hLen = cx_pkcs1_get_hash_len(hID);
494 return cx_pkcs1_emsa_pss_verify_with_salt_len(hID, em, emBits, mHash, mHashLen, hLen);
500cx_err_t cx_pkcs1_eme_v1o5_encode(cx_md_t hID,
510 if ((3 + mLen) >= emLen) {
511 return CX_INVALID_PARAMETER;
513 PSLen = emLen - (3 + mLen);
515 memcpy(em + 2 + PSLen + 1, m, mLen);
518 cx_rng_no_throw(em + 2, PSLen);
519 for (offset = 2 + PSLen - 1; offset >= 2; offset--) {
520 if (em[offset] == 0) {
528size_t cx_pkcs1_eme_v1o5_decode(cx_md_t hID, uint8_t *em,
size_t emLen, uint8_t *m,
size_t mLen)
533 if ((em[0]) || (em[1] != 2)) {
538 while (offset < emLen) {
539 if (em[offset] == 0) {
544 if (offset == emLen) {
549 if (mLen < emLen - offset) {
552 mLen = emLen - offset;
553 memmove(m, em + offset, mLen);
560cx_err_t cx_pkcs1_eme_oaep_encode(cx_md_t hID,
571 const uint8_t *lHash;
575 hLen = cx_pkcs1_get_hash_len(hID);
576 lHash = cx_pkcs1_get_hash_oeap(hID, &lHashLen);
577 if (hLen == 0 || lHash == NULL) {
578 return CX_INVALID_PARAMETER;
581 if ((hLen + 1) >= emLen) {
582 return CX_INVALID_PARAMETER;
584 mDBlen = emLen - (hLen + 1);
585 if ((mLen + 2 * hLen + 2) >= emLen) {
586 return CX_INVALID_PARAMETER;
588 psLen = emLen - (mLen + 2 * hLen + 2);
591 cx_rng_no_throw(seed, hLen);
595 memcpy(em + offset, lHash, lHashLen);
597 memset(em + offset, 0, psLen);
601 memcpy(em + offset, m, mLen);
606 CX_CHECK(cx_pkcs1_MGF1(hID, seed, hLen,
G_cx.pkcs1.MGF1, mDBlen));
609 CX_CHECK(cx_pkcs1_MGF1(hID, em + 1 + hLen, mDBlen,
G_cx.pkcs1.MGF1, hLen));
610 memcpy(em + 1, seed, hLen);
617cx_err_t cx_pkcs1_eme_oaep_decode(cx_md_t hID, uint8_t *em,
size_t emLen, uint8_t *m,
size_t *mLen)
622 const uint8_t *lHash;
626 hLen = cx_pkcs1_get_hash_len(hID);
627 lHash = cx_pkcs1_get_hash_oeap(hID, &lHashLen);
628 if (hLen == 0 || lHash == NULL) {
629 return CX_INVALID_PARAMETER;
631 if ((hLen + 1) >= emLen) {
632 return CX_INVALID_PARAMETER;
634 mDBlen = emLen - (hLen + 1);
637 CX_CHECK(cx_pkcs1_MGF1(hID, em + 1 + hLen, mDBlen,
G_cx.pkcs1.MGF1, hLen));
639 CX_CHECK(cx_pkcs1_MGF1(hID, em + 1, hLen,
G_cx.pkcs1.MGF1, mDBlen));
644 return CX_INVALID_PARAMETER;
646 if (memcmp(em + 1 + hLen, lHash, hLen) != 0) {
647 return CX_INVALID_PARAMETER;
650 for (offset = 1 + hLen + lHashLen; offset < emLen; offset++) {
651 if (em[offset] != 0) {
655 if ((offset == emLen) || (em[offset] != 0x01)) {
656 return CX_INVALID_PARAMETER;
661 if (*mLen < emLen - offset) {
662 return CX_INVALID_PARAMETER;
665 *mLen = emLen - offset;
666 memmove(m, em + offset, *mLen);
void cx_memxor(uint8_t *buf1, const uint8_t *buf2, size_t len)
Random Number Generation.