Path: blob/main/crypto/libecc/src/examples/sig/rsa/rsa.c
34927 views
/*1* Copyright (C) 2021 - This file is part of libecc project2*3* Authors:4* Ryad BENADJILA <[email protected]>5* Arnaud EBALARD <[email protected]>6*7* This software is licensed under a dual BSD and GPL v2 license.8* See LICENSE file at the root folder of the project.9*/10#include "rsa.h"11#include "rsa_tests.h"121314/* We include the rand external dependency because we have to generate15* some random data for the padding.16*/17#include <libecc/external_deps/rand.h>18/* We include the printf external dependency for printf output */19#include <libecc/external_deps/print.h>20/* We include our common helpers */21#include "../common/common.h"222324/*25* The purpose of this example is to implement the RSA26* related algorithms as per RFC 8017 and ISO/IEC 9796-2 based27* on libecc arithmetic primitives.28*29* XXX: Please be aware that libecc has been designed for Elliptic30* Curve cryptography, and as so the arithmetic primitives are31* not optimized for big numbers >= 1024 bits usually used for RSA.32* Additionnaly, a hard limit of our NN values makes it impossible33* to exceed ~5300 bits in the best case (words of size 64 bits).34*35* All in all, please see this as a proof of concept of implementing36* RFC 8017 rather than a production code. Use it at your own risk!37*38* !! DISCLAIMER !!39* ================40* Although some efforts have been put on providing a clean code and although many of41* the underlying arithmetic primitives are constant time, only basic efforts have42* been deployed to prevent advanced side channels (e.g. to protect the private values43* against elaborate microarchitectural side-channels and so on). The modular exponentation44* uses a Montgomery Ladder, and message blinding is performed to mitigate basic SCA.45* Please note that the modular exponentation is NOT constant time wrt the MSB of46* the private exponent, which should be OK in the general case as this leak is less47* critical than for DSA and ECDSA nonces in scalar multiplication (raising HNP issues48* in these last cases).49* Optionally, when BLINDING=1 is activated, exponent blinding is used by adding a50* "small" (128 bits) multiple of the "order" (this is left as optional because of51* the big impacts on performance), somehow limiting the modular exponentiation MSB52* issue at the expense of performance.53*54* Padding oracles (Bleichenbacher, Manger) in RSA PKCS#1 v1.5 and RSA-OAEP decryption55* primitives are taken into account, although no absolute guarantee can be made on this56* (and mostly: these oracles also heavily depend on what the upper layer callers do).57*58* Fault injection attacks "a la Bellcore" are protected using a sanity check that59* the exponentiation to the public exponent provides the same input as the operation60* using the private exponent.61*62* !!NOTE: only the *_hardened* suffixed APIs are protected, the non suffixed ones are63* *NOT* protected. This is mainly due to the fact that the protections use the public64* key while the RFC APIs handling private operations only take the private key as65* input. Hence, please *USE* the *_hardened* APIs if unsure about your usage context!66*67* Also, as for all other libecc primitives, beware of randomness sources. By default,68* the library uses the OS random sources (e.g. "/dev/urandom"), but the user69* is encouraged to adapt the ../external_deps/rand.c source file to combine70* multiple sources and add entropy there depending on the context where this71* code is integrated. The security level of all the cryptographic primitives72* heavily relies on random sources quality.73*74* All-in-all, this piece of code can be useful in some contexts, or risky to75* use in other sensitive ones where advanced side-channels or fault attacks76* have to be considered. Use this RSA code knowingly and at your own risk!77*78*/7980int rsa_import_pub_key(rsa_pub_key *pub, const u8 *n,81u16 nlen, const u8 *e, u16 elen)82{83int ret;8485MUST_HAVE((pub != NULL), ret, err);8687/* Import our big numbers */88ret = nn_init_from_buf(&(pub->n), n, nlen); EG(ret, err);89ret = nn_init_from_buf(&(pub->e), e, elen);9091err:92if(ret && (pub != NULL)){93IGNORE_RET_VAL(local_memset(pub, 0, sizeof(rsa_pub_key)));94}9596return ret;97}9899int rsa_import_simple_priv_key(rsa_priv_key *priv,100const u8 *n, u16 nlen, const u8 *d, u16 dlen,101const u8 *p, u16 plen, const u8 *q, u16 qlen)102{103int ret;104105MUST_HAVE((priv != NULL), ret, err);106107MUST_HAVE(((p != NULL) && (q != NULL)) || ((p == NULL) && (q == NULL)), ret, err);108109/* Import our big numbers */110if((p == NULL) || (q == NULL)){111priv->type = RSA_SIMPLE;112ret = nn_init_from_buf(&(priv->key.s.n), n, nlen); EG(ret, err);113ret = nn_init_from_buf(&(priv->key.s.d), d, dlen); EG(ret, err);114}115else{116priv->type = RSA_SIMPLE_PQ;117ret = nn_init_from_buf(&(priv->key.s_pq.n), n, nlen); EG(ret, err);118ret = nn_init_from_buf(&(priv->key.s_pq.d), d, dlen); EG(ret, err);119ret = nn_init_from_buf(&(priv->key.s_pq.p), p, plen); EG(ret, err);120ret = nn_init_from_buf(&(priv->key.s_pq.q), q, qlen); EG(ret, err);121}122123err:124if(ret && (priv != NULL)){125IGNORE_RET_VAL(local_memset(priv, 0, sizeof(rsa_priv_key)));126}127128return ret;129}130131int rsa_import_crt_priv_key(rsa_priv_key *priv,132const u8 *p, u16 plen,133const u8 *q, u16 qlen,134const u8 *dP, u16 dPlen,135const u8 *dQ, u16 dQlen,136const u8 *qInv, u16 qInvlen,137const u8 **coeffs, u16 *coeffslens, u8 u)138{139int ret;140141MUST_HAVE((priv != NULL), ret, err);142143priv->type = RSA_CRT;144/* Import our big numbers */145ret = nn_init_from_buf(&(priv->key.crt.p), p, plen); EG(ret, err);146ret = nn_init_from_buf(&(priv->key.crt.q), q, qlen); EG(ret, err);147ret = nn_init_from_buf(&(priv->key.crt.dP), dP, dPlen); EG(ret, err);148ret = nn_init_from_buf(&(priv->key.crt.dQ), dQ, dQlen); EG(ret, err);149ret = nn_init_from_buf(&(priv->key.crt.qInv), qInv, qInvlen); EG(ret, err);150151priv->key.crt.u = 0;152153/* Import the optional coefficients if necessary */154if(coeffs != NULL){155unsigned int i;156157MUST_HAVE((coeffslens != NULL), ret, err);158MUST_HAVE((u > 0) && (u < MAX_CRT_COEFFS), ret, err);159160priv->key.crt.u = u;161162for(i = 0; i < (3*u); i += 3){163rsa_priv_key_crt_coeffs *cur = &(priv->key.crt.coeffs[(i / 3)]);164165ret = nn_init_from_buf(&(cur->r), coeffs[i], coeffslens[i]); EG(ret, err);166ret = nn_init_from_buf(&(cur->d), coeffs[i + 1], coeffslens[i + 1]); EG(ret, err);167ret = nn_init_from_buf(&(cur->t), coeffs[i + 2], coeffslens[i + 2]); EG(ret, err);168}169}170171err:172if(ret && (priv != NULL)){173IGNORE_RET_VAL(local_memset(priv, 0, sizeof(rsa_priv_key)));174}175return ret;176}177178/* I2OSP - Integer-to-Octet-String primitive179* (as decribed in section 4.1 of RFC 8017)180*/181int rsa_i2osp(nn_src_t x, u8 *buf, u32 buflen)182{183int ret;184185/* Size check */186MUST_HAVE((buflen <= 0xffff), ret, err);187ret = _i2osp(x, buf, (u16)buflen);188189err:190return ret;191}192193/* OS2IP - Octet-String-to-Integer primitive194* (as decribed in section 4.2 of RFC 8017)195*/196int rsa_os2ip(nn_t x, const u8 *buf, u32 buflen)197{198int ret;199200/* Size check */201MUST_HAVE((buflen <= 0xffff), ret, err);202ret = _os2ip(x, buf, (u16)buflen);203204err:205return ret;206}207208/* The raw RSAEP function as defined in RFC 8017 section 5.1.1209* Input: an RSA public key and a big int message210* Output: a big int ciphertext211* Assumption: RSA public key K is valid212*/213int rsaep(const rsa_pub_key *pub, nn_src_t m, nn_t c)214{215int ret, cmp;216nn_src_t n, e;217218/* Sanity checks */219MUST_HAVE((pub != NULL), ret, err);220221/* Make things more readable */222n = &(pub->n);223e = &(pub->e);224225/* Sanity checks */226ret = nn_check_initialized(n); EG(ret, err);227ret = nn_check_initialized(e); EG(ret, err);228229/* Check that m is indeed in [0, n-1], trigger an error if not */230MUST_HAVE((!nn_cmp(m, n, &cmp)) && (cmp < 0), ret, err);231232/* Compute c = m^e mod n233* NOTE: we use our internal *insecure* modular exponentation as we234* are handling public key and data.235*/236ret = _nn_mod_pow_insecure(c, m, e, n);237238err:239PTR_NULLIFY(n);240PTR_NULLIFY(e);241242return ret;243}244245#ifdef USE_SIG_BLINDING246#define RSA_EXPONENT_BLINDING_SIZE 128247/*248* Blind an exponent with a "small" multiple (of size "bits") of the input mod or (mod-1).249* We use a relatively small multiple mainly because of potential big performance impacts on250* modular exponentiation.251*/252ATTRIBUTE_WARN_UNUSED_RET static int _rsa_blind_exponent(nn_src_t e, nn_src_t mod, nn_t out, bitcnt_t bits, u8 dec)253{254int ret, check;255nn b;256b.magic = WORD(0);257258ret = nn_init(&b, 0); EG(ret, err);259ret = nn_init(out, 0); EG(ret, err);260261ret = nn_one(out); EG(ret, err);262ret = nn_lshift(out, out, bits); EG(ret, err);263ret = nn_iszero(out, &check); EG(ret, err);264/* Check for overflow */265MUST_HAVE(!check, ret, err);266267/* Get a random value of "bits" count */268ret = nn_get_random_mod(&b, out); EG(ret, err);269270if(dec){271ret = nn_copy(out, mod); EG(ret, err);272ret = nn_dec(out, out); EG(ret, err);273ret = nn_mul(&b, &b, out); EG(ret, err);274}275else{276ret = nn_mul(&b, &b, mod); EG(ret, err);277}278279ret = nn_add(out, e, &b);280281err:282nn_uninit(&b);283284return ret;285}286#endif287288/* The raw RSADP function as defined in RFC 8017 section 5.1.2289* Input: an RSA private key 'priv' and a big int ciphertext 'c'290* Output: a big int clear message 'm'291* Assumption: RSA private key 'priv' is valid292*/293ATTRIBUTE_WARN_UNUSED_RET static int rsadp_crt_coeffs(const rsa_priv_key *priv, nn_src_t c, nn_t m, u8 u)294{295int ret;296unsigned int i;297nn_src_t r_i, d_i, t_i, r_i_1;298nn m_i, h, R;299m_i.magic = h.magic = R.magic = WORD(0);300301/* Sanity check on u */302MUST_HAVE((u < MAX_CRT_COEFFS), ret, err);303304ret = nn_init(&m_i, 0); EG(ret, err);305ret = nn_init(&h, 0); EG(ret, err);306ret = nn_init(&R, 0); EG(ret, err);307/* NOTE: this is an internal function, sanity checks on priv and u have308* been performed by the callers.309*/310/* R = r_1 */311ret = nn_copy(&R, &(priv->key.crt.coeffs[0].r)); EG(ret, err);312/* Loop */313for(i = 1; i < u; i++){314r_i_1 = &(priv->key.crt.coeffs[i-1].r);315r_i = &(priv->key.crt.coeffs[i].r);316d_i = &(priv->key.crt.coeffs[i].d);317t_i = &(priv->key.crt.coeffs[i].t);318319/* Sanity checks */320ret = nn_check_initialized(r_i_1); EG(ret, err);321ret = nn_check_initialized(r_i); EG(ret, err);322ret = nn_check_initialized(d_i); EG(ret, err);323ret = nn_check_initialized(t_i); EG(ret, err);324325/* m_i = c^(d_i) mod r_i */326#ifdef USE_SIG_BLINDING327ret = _rsa_blind_exponent(d_i, r_i, &h, (bitcnt_t)RSA_EXPONENT_BLINDING_SIZE, 1); EG(ret, err);328ret = nn_mod_pow(&m_i, c, &h, r_i); EG(ret, err);329#else330ret = nn_mod_pow(&m_i, c, d_i, r_i); EG(ret, err);331#endif332/* R = R * r_(i-1) */333ret = nn_mul(&R, &R, r_i_1); EG(ret, err);334/* h = (m_i - m) * t_i mod r_i */335ret = nn_mod(&h, m, r_i); EG(ret, err);336ret = nn_mod_sub(&h, &m_i, &h, r_i); EG(ret, err);337ret = nn_mod_mul(&h, &h, t_i, r_i); EG(ret, err);338/* m = m + R * h */339ret = nn_mul(&h, &R, &h); EG(ret, err);340ret = nn_add(m, m, &h); EG(ret, err);341}342343err:344nn_uninit(&m_i);345nn_uninit(&h);346nn_uninit(&R);347348PTR_NULLIFY(r_i);349PTR_NULLIFY(d_i);350PTR_NULLIFY(t_i);351PTR_NULLIFY(r_i_1);352353return ret;354}355356ATTRIBUTE_WARN_UNUSED_RET static int rsadp_crt(const rsa_priv_key *priv, nn_src_t c, nn_t m)357{358int ret;359nn_src_t p, q, dP, dQ, qInv;360nn m_1, m_2, h, msb_fixed;361u8 u;362m_1.magic = m_2.magic = h.magic = WORD(0);363364ret = nn_init(&m_1, 0); EG(ret, err);365ret = nn_init(&m_2, 0); EG(ret, err);366ret = nn_init(&h, 0); EG(ret, err);367ret = nn_init(&msb_fixed, 0); EG(ret, err);368369/* Make things more readable */370p = &(priv->key.crt.p);371q = &(priv->key.crt.q);372dP = &(priv->key.crt.dP);373dQ = &(priv->key.crt.dQ);374qInv = &(priv->key.crt.qInv);375u = priv->key.crt.u;376377/* Sanity checks */378ret = nn_check_initialized(p); EG(ret, err);379ret = nn_check_initialized(q); EG(ret, err);380ret = nn_check_initialized(dP); EG(ret, err);381ret = nn_check_initialized(dQ); EG(ret, err);382ret = nn_check_initialized(qInv); EG(ret, err);383384/* m_1 = c^dP mod p */385#ifdef USE_SIG_BLINDING386ret = _rsa_blind_exponent(dP, p, &h, (bitcnt_t)RSA_EXPONENT_BLINDING_SIZE, 1); EG(ret, err);387ret = nn_mod_pow(&m_1, c, &h, p); EG(ret, err);388#else389ret = nn_mod_pow(&m_1, c, dP, p); EG(ret, err);390#endif391/* m_2 = c^dQ mod q */392#ifdef USE_SIG_BLINDING393ret = _rsa_blind_exponent(dQ, q, &h, (bitcnt_t)RSA_EXPONENT_BLINDING_SIZE, 1); EG(ret, err);394ret = nn_mod_pow(&m_2, c, &h, q); EG(ret, err);395#else396ret = nn_mod_pow(&m_2, c, dQ, q); EG(ret, err);397#endif398/* h = (m_1 - m_2) * qInv mod p */399ret = nn_mod(&h, &m_2, p); EG(ret, err);400ret = nn_mod_sub(&h, &m_1, &h, p); EG(ret, err);401ret = nn_mod_mul(&h, &h, qInv, p); EG(ret, err);402/* m = m_2 + q * h */403ret = nn_mul(m, &h, q); EG(ret, err);404ret = nn_add(m, &m_2, m); EG(ret, err);405406if(u > 1){407ret = rsadp_crt_coeffs(priv, c, m, u);408}409410err:411nn_uninit(&m_1);412nn_uninit(&m_2);413nn_uninit(&h);414415PTR_NULLIFY(p);416PTR_NULLIFY(q);417PTR_NULLIFY(dP);418PTR_NULLIFY(dQ);419PTR_NULLIFY(qInv);420421return ret;422}423424ATTRIBUTE_WARN_UNUSED_RET static int rsadp_nocrt(const rsa_priv_key *priv, nn_src_t c, nn_t m)425{426int ret, cmp;427nn_src_t n, d, p, q;428#ifdef USE_SIG_BLINDING429nn b1, b2;430b1.magic = b2.magic = WORD(0);431#endif432/* Make things more readable */433if(priv->type == RSA_SIMPLE){434n = &(priv->key.s.n);435d = &(priv->key.s.d);436}437else if(priv->type == RSA_SIMPLE_PQ){438n = &(priv->key.s_pq.n);439d = &(priv->key.s_pq.d);440}441else{442ret = -1;443goto err;444}445/* Sanity checks */446ret = nn_check_initialized(n); EG(ret, err);447ret = nn_check_initialized(d); EG(ret, err);448/* Check that c is indeed in [0, n-1], trigger an error if not */449MUST_HAVE((!nn_cmp(c, n, &cmp)) && (cmp < 0), ret, err);450451/* Compute m = c^d mod n */452#ifdef USE_SIG_BLINDING453/* When we are asked to use exponent blinding, we MUST have a RSA_SIMPLE_PQ454* type key in order to be able to compute our Phi(n) = (p-1)(q-1) and perform455* the blinding.456*/457if(priv->type == RSA_SIMPLE_PQ){458p = &(priv->key.s_pq.p);459q = &(priv->key.s_pq.q);460ret = nn_init(&b1, 0); EG(ret, err);461ret = nn_init(&b2, 0); EG(ret, err);462ret = nn_dec(&b1, p); EG(ret, err);463ret = nn_dec(&b2, q); EG(ret, err);464ret = nn_mul(&b1, &b1, &b2); EG(ret, err);465ret = _rsa_blind_exponent(d, &b1, &b2, (bitcnt_t)RSA_EXPONENT_BLINDING_SIZE, 0); EG(ret, err);466ret = nn_mod_pow(m, c, &b2, n); EG(ret, err);467}468else{469ret = -1;470goto err;471}472#else473FORCE_USED_VAR(p);474FORCE_USED_VAR(q);475ret = nn_mod_pow(m, c, d, n);476#endif477478err:479#ifdef USE_SIG_BLINDING480nn_uninit(&b1);481nn_uninit(&b2);482#endif483PTR_NULLIFY(n);484PTR_NULLIFY(d);485PTR_NULLIFY(p);486PTR_NULLIFY(q);487488return ret;489}490491int rsadp(const rsa_priv_key *priv, nn_src_t c, nn_t m)492{493int ret;494495/* Sanity checks */496MUST_HAVE((priv != NULL), ret, err);497498/* Do we have a simple or a CRT key? */499if((priv->type == RSA_SIMPLE) || (priv->type == RSA_SIMPLE_PQ)){500ret = rsadp_nocrt(priv, c, m); EG(ret, err);501}502else if(priv->type == RSA_CRT){503ret = rsadp_crt(priv, c, m); EG(ret, err);504}505else{506ret = -1;507goto err;508}509510err:511return ret;512}513514/*515* The "hardened" version of rsadp that uses message blinding as well516* as output check for Bellcore style fault attacks.517*518*/519int rsadp_hardened(const rsa_priv_key *priv, const rsa_pub_key *pub, nn_src_t c, nn_t m)520{521int ret, check;522nn_src_t n, e;523nn b, binv;524b.magic = binv.magic = WORD(0);525526/* Make things more readable */527n = &(pub->n);528e = &(pub->e);529530/* Sanity checks */531MUST_HAVE((priv != NULL) && (pub != NULL), ret, err);532533/* Blind the message: get a random value for b prime with n534* and compute its modular inverse.535*/536ret = nn_init(&b, 0); EG(ret, err);537ret = nn_init(&binv, 0); EG(ret, err);538ret = -1;539while(ret){540ret = nn_get_random_mod(&b, n); EG(ret, err);541ret = nn_modinv(&binv, &b, n);542}543/* Exponentiate the blinder to the public value */544ret = _nn_mod_pow_insecure(m, &b, e, n); EG(ret, err);545/* Perform message blinding */546ret = nn_mod_mul(&b, m, c, n); EG(ret, err);547548/* Perform rsadp on the blinded message */549ret = rsadp(priv, &b, m); EG(ret, err);550551/* Unblind the result */552ret = nn_mod_mul(m, m, &binv, n); EG(ret, err);553554/* Now perform the public operation to check the result.555* This is useful against some fault attacks (Bellcore style).556*/557ret = rsaep(pub, m, &b); EG(ret, err);558ret = nn_cmp(c, &b, &check); EG(ret, err);559MUST_HAVE((check == 0), ret, err);560561err:562nn_uninit(&b);563nn_uninit(&binv);564565PTR_NULLIFY(n);566PTR_NULLIFY(e);567568return ret;569}570571/* The raw RSASP1 function as defined in RFC 8017 section 5.2.1572* Input: an RSA private key 'priv' and a big int message 'm'573* Output: a big int signature 's'574* Assumption: RSA private key 'priv' is valid575*/576int rsasp1(const rsa_priv_key *priv, nn_src_t m, nn_t s)577{578return rsadp(priv, m, s);579}580581/*582* The "hardened" version of rsasp1 that uses message blinding as well583* as optional exponent blinding.584*585*/586int rsasp1_hardened(const rsa_priv_key *priv, const rsa_pub_key *pub, nn_src_t m, nn_t s)587{588return rsadp_hardened(priv, pub, m, s);589}590591592/* The raw RSAVP1 function as defined in RFC 8017 section 5.2.2593* Input: an RSA public key 'pub' and a big int signature 's'594* Output: a big int ciphertext 'm'595* Assumption: RSA public key 'pub' is valid596*/597int rsavp1(const rsa_pub_key *pub, nn_src_t s, nn_t m)598{599return rsaep(pub, s, m);600}601602ATTRIBUTE_WARN_UNUSED_RET static int rsa_digestinfo_from_hash(gen_hash_alg_type gen_hash_type, u8 *digestinfo, u32 *digestinfo_len)603{604int ret;605606/* Sanity check */607MUST_HAVE((digestinfo_len != NULL), ret, err);608609switch(gen_hash_type){610case HASH_MD2:{611const u8 _digestinfo[] = { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a,6120x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x02,6130x05, 0x00, 0x04, 0x10 };614MUST_HAVE(((*digestinfo_len) >= sizeof(_digestinfo)), ret, err);615ret = local_memcpy(digestinfo, _digestinfo, sizeof(_digestinfo)); EG(ret, err);616(*digestinfo_len) = sizeof(_digestinfo);617break;618}619case HASH_MD4:{620const u8 _digestinfo[] = { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a,6210x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x04,6220x05, 0x00, 0x04, 0x10 };623MUST_HAVE(((*digestinfo_len) >= sizeof(_digestinfo)), ret, err);624ret = local_memcpy(digestinfo, _digestinfo, sizeof(_digestinfo)); EG(ret, err);625(*digestinfo_len) = sizeof(_digestinfo);626break;627}628case HASH_MD5:{629const u8 _digestinfo[] = { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a,6300x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05,6310x05, 0x00, 0x04, 0x10 };632MUST_HAVE(((*digestinfo_len) >= sizeof(_digestinfo)), ret, err);633ret = local_memcpy(digestinfo, _digestinfo, sizeof(_digestinfo)); EG(ret, err);634(*digestinfo_len) = sizeof(_digestinfo);635break;636}637case HASH_SHA0:{638const u8 _digestinfo[] = { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b,6390x0e, 0x03, 0x02, 0x12, 0x05, 0x00, 0x04,6400x14 };641MUST_HAVE(((*digestinfo_len) >= sizeof(_digestinfo)), ret, err);642ret = local_memcpy(digestinfo, _digestinfo, sizeof(_digestinfo)); EG(ret, err);643(*digestinfo_len) = sizeof(_digestinfo);644break;645}646case HASH_SHA1:{647const u8 _digestinfo[] = { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b,6480x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04,6490x14 };650MUST_HAVE(((*digestinfo_len) >= sizeof(_digestinfo)), ret, err);651ret = local_memcpy(digestinfo, _digestinfo, sizeof(_digestinfo)); EG(ret, err);652(*digestinfo_len) = sizeof(_digestinfo);653break;654}655case HASH_SHA224:{656const u8 _digestinfo[] = { 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60,6570x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,6580x04, 0x05, 0x00, 0x04, 0x1c };659MUST_HAVE(((*digestinfo_len) >= sizeof(_digestinfo)), ret, err);660ret = local_memcpy(digestinfo, _digestinfo, sizeof(_digestinfo)); EG(ret, err);661(*digestinfo_len) = sizeof(_digestinfo);662break;663}664case HASH_SHA256:{665const u8 _digestinfo[] = { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,6660x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,6670x01, 0x05, 0x00, 0x04, 0x20 };668MUST_HAVE(((*digestinfo_len) >= sizeof(_digestinfo)), ret, err);669ret = local_memcpy(digestinfo, _digestinfo, sizeof(_digestinfo)); EG(ret, err);670(*digestinfo_len) = sizeof(_digestinfo);671break;672}673case HASH_SHA384:{674const u8 _digestinfo[] = { 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60,6750x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,6760x02, 0x05, 0x00, 0x04, 0x30 };677MUST_HAVE(((*digestinfo_len) >= sizeof(_digestinfo)), ret, err);678ret = local_memcpy(digestinfo, _digestinfo, sizeof(_digestinfo)); EG(ret, err);679(*digestinfo_len) = sizeof(_digestinfo);680break;681}682case HASH_SHA512:{683const u8 _digestinfo[] = { 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60,6840x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,6850x03, 0x05, 0x00, 0x04, 0x40 };686MUST_HAVE(((*digestinfo_len) >= sizeof(_digestinfo)), ret, err);687ret = local_memcpy(digestinfo, _digestinfo, sizeof(_digestinfo)); EG(ret, err);688(*digestinfo_len) = sizeof(_digestinfo);689break;690}691case HASH_SHA512_224:{692const u8 _digestinfo[] = { 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60,6930x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,6940x05, 0x05, 0x00, 0x04, 0x1c };695MUST_HAVE(((*digestinfo_len) >= sizeof(_digestinfo)), ret, err);696ret = local_memcpy(digestinfo, _digestinfo, sizeof(_digestinfo)); EG(ret, err);697(*digestinfo_len) = sizeof(_digestinfo);698break;699}700case HASH_SHA512_256:{701const u8 _digestinfo[] = { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,7020x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,7030x06, 0x05, 0x00, 0x04, 0x20 };704MUST_HAVE(((*digestinfo_len) >= sizeof(_digestinfo)), ret, err);705ret = local_memcpy(digestinfo, _digestinfo, sizeof(_digestinfo)); EG(ret, err);706(*digestinfo_len) = sizeof(_digestinfo);707break;708}709case HASH_RIPEMD160:{710const u8 _digestinfo[] = { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b,7110x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04,7120x14 };713MUST_HAVE(((*digestinfo_len) >= sizeof(_digestinfo)), ret, err);714ret = local_memcpy(digestinfo, _digestinfo, sizeof(_digestinfo)); EG(ret, err);715(*digestinfo_len) = sizeof(_digestinfo);716break;717}718/* The following SHA-3 oids have been taken from719* https://www.ietf.org/archive/id/draft-jivsov-openpgp-sha3-01.txt720*721* The specific case of SHA3-224 is infered from the OID of SHA3-224 although722* not standardized.723*/724case HASH_SHA3_224:{725const u8 _digestinfo[] = { 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60,7260x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,7270x07, 0x05, 0x00, 0x04, 0x1c };728MUST_HAVE(((*digestinfo_len) >= sizeof(_digestinfo)), ret, err);729ret = local_memcpy(digestinfo, _digestinfo, sizeof(_digestinfo)); EG(ret, err);730(*digestinfo_len) = sizeof(_digestinfo);731break;732}733case HASH_SHA3_256:{734const u8 _digestinfo[] = { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,7350x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,7360x08, 0x05, 0x00, 0x04, 0x20 };737MUST_HAVE(((*digestinfo_len) >= sizeof(_digestinfo)), ret, err);738ret = local_memcpy(digestinfo, _digestinfo, sizeof(_digestinfo)); EG(ret, err);739(*digestinfo_len) = sizeof(_digestinfo);740break;741}742case HASH_SHA3_384:{743const u8 _digestinfo[] = { 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60,7440x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,7450x09, 0x05, 0x00, 0x04, 0x30 };746MUST_HAVE(((*digestinfo_len) >= sizeof(_digestinfo)), ret, err);747ret = local_memcpy(digestinfo, _digestinfo, sizeof(_digestinfo)); EG(ret, err);748(*digestinfo_len) = sizeof(_digestinfo);749break;750}751case HASH_SHA3_512:{752const u8 _digestinfo[] = { 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60,7530x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,7540x0a ,0x05, 0x00, 0x04, 0x40 };755MUST_HAVE(((*digestinfo_len) >= sizeof(_digestinfo)), ret, err);756ret = local_memcpy(digestinfo, _digestinfo, sizeof(_digestinfo)); EG(ret, err);757(*digestinfo_len) = sizeof(_digestinfo);758break;759}760/* For SM3, the "RSA Signing with SM3" OID is taken from:761* http://gmssl.org/docs/oid.html762*/763case HASH_SM3:{764const u8 _digestinfo[] = { 0x30, 0x30, 0x30, 0x0d, 0x06, 0x08, 0x2A,7650x81, 0x1c, 0xcf, 0x55, 0x01, 0x83, 0x78,7660x05, 0x00, 0x04, 0x20 };767MUST_HAVE(((*digestinfo_len) >= sizeof(_digestinfo)), ret, err);768ret = local_memcpy(digestinfo, _digestinfo, sizeof(_digestinfo)); EG(ret, err);769(*digestinfo_len) = sizeof(_digestinfo);770break;771}772default:{773ret = -1;774goto err;775}776}777778err:779return ret;780}781782/* GF1 as a mask generation function as described in RFC 8017 Appendix B.2.1783* z is the 'seed', and zlen its length784*/785ATTRIBUTE_WARN_UNUSED_RET static int _mgf1(const u8 *z, u16 zlen,786u8 *mask, u64 masklen,787gen_hash_alg_type mgf_hash_type)788{789int ret;790u8 hlen, block_size;791u32 c, ceil;792u8 C[4];793const u8 *input[3] = { z, C, NULL };794u32 ilens[3] = { zlen, 4, 0 };795u8 digest[MAX_DIGEST_SIZE];796797/* Zeroize local variables */798ret = local_memset(C, 0, sizeof(C)); EG(ret, err);799ret = local_memset(digest, 0, sizeof(digest)); EG(ret, err);800801/* Sanity checks */802MUST_HAVE((z != NULL) && (mask != NULL), ret, err);803804ret = gen_hash_get_hash_sizes(mgf_hash_type, &hlen, &block_size); EG(ret, err);805MUST_HAVE((hlen <= MAX_DIGEST_SIZE), ret, err);806807/* masklen must be < 2**32 * hlen */808MUST_HAVE((masklen < ((u64)hlen * ((u64)0x1 << 32))), ret, err);809ceil = (u32)(masklen / hlen) + !!(masklen % hlen);810811for(c = 0; c < ceil; c++){812/* 3.A: C = I2OSP (counter, 4) */813C[0] = (u8)((c >> 24) & 0xff);814C[1] = (u8)((c >> 16) & 0xff);815C[2] = (u8)((c >> 8) & 0xff);816C[3] = (u8)((c >> 0) & 0xff);817818/* 3.B + 4. */819if ((masklen % hlen) && (c == (ceil - 1))) { /* need last chunk smaller than hlen */820ret = gen_hash_hfunc_scattered(input, ilens, digest, mgf_hash_type); EG(ret, err);821ret = local_memcpy(&mask[c * hlen], digest, (u32)(masklen % hlen)); EG(ret, err);822} else { /* common case, i.e. complete chunk */823ret = gen_hash_hfunc_scattered(input, ilens, &mask[c * hlen], mgf_hash_type); EG(ret, err);824}825}826err:827return ret;828}829830/* EMSA-PSS-ENCODE encoding as described in RFC 8017 section 9.1.1831* NOTE: we enforce MGF1 as a mask generation function832*/833int emsa_pss_encode(const u8 *m, u32 mlen, u8 *em, u32 embits,834u16 *eminlen, gen_hash_alg_type gen_hash_type, gen_hash_alg_type mgf_hash_type,835u32 saltlen, const u8 *forced_salt)836{837int ret;838u8 hlen, block_size;839u8 mhash[MAX_DIGEST_SIZE];840u8 h[MAX_DIGEST_SIZE];841u8 zeroes[8];842/* Reasonable sizes:843* NOTE: for the cases where the salt exceeds this size, we return an error844* alhough this should not happen if our underlying libecc supports the current845* modulus size.846*/847u8 salt[NN_USABLE_MAX_BYTE_LEN];848u8 *dbmask = em;849const u8 *input[2] = { m, NULL };850u32 ilens[2] = { mlen, 0 };851u32 emlen, dblen, pslen;852unsigned int i;853u8 mask;854const u8 *input_[4] = { zeroes, mhash, salt, NULL };855u32 ilens_[4];856857/* Zeroize local variables */858ret = local_memset(mhash, 0, sizeof(mhash)); EG(ret, err);859ret = local_memset(h, 0, sizeof(h)); EG(ret, err);860ret = local_memset(salt, 0, sizeof(salt)); EG(ret, err);861ret = local_memset(zeroes, 0, sizeof(zeroes)); EG(ret, err);862ret = local_memset(ilens_, 0, sizeof(ilens_)); EG(ret, err);863864/* Sanity checks */865MUST_HAVE((m != NULL) && (em != NULL) && (eminlen != NULL), ret, err);866867/* We only allow salt up to a certain size */868MUST_HAVE((saltlen <= sizeof(salt)), ret, err);869emlen = BYTECEIL(embits);870MUST_HAVE((emlen < (u32)((u32)0x1 << 16)), ret, err);871872/* Check that we have enough room for the output */873MUST_HAVE(((*eminlen) >= emlen), ret, err);874875/* Get the used hash information */876ret = gen_hash_get_hash_sizes(gen_hash_type, &hlen, &block_size); EG(ret, err);877MUST_HAVE((hlen <= MAX_DIGEST_SIZE), ret, err);878879/* emBits at least 8hLen + 8sLen + 9 */880MUST_HAVE((embits >= ((8*(u32)hlen) + (8*(u32)saltlen) + 9)), ret, err);881882/* If emLen < hLen + sLen + 2, output "encoding error" and stop. */883MUST_HAVE((emlen >= ((u32)hlen + (u32)saltlen + 2)), ret, err);884885/* mHash = Hash(M) */886ret = gen_hash_hfunc_scattered(input, ilens, mhash, gen_hash_type); EG(ret, err);887888/* Generate a random octet string salt of length sLen; if sLen = 0889* then salt is the empty string.890* M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt;891* H = Hash(M'),892*/893if(forced_salt != NULL){894/* We are given a forced salt, use it */895ret = local_memcpy(salt, forced_salt, saltlen); EG(ret, err);896}897else{898/* We only support generating salts of size <= 2**16 */899MUST_HAVE((saltlen <= 0xffff), ret, err);900/* Get random salt */901ret = get_random(salt, (u16)saltlen); EG(ret, err);902}903ilens_[0] = sizeof(zeroes);904ilens_[1] = hlen;905ilens_[2] = saltlen;906ilens_[3] = 0;907ret = gen_hash_hfunc_scattered(input_, ilens_, h, gen_hash_type); EG(ret, err);908909/* dbMask = MGF(H, emLen - hLen - 1)910* NOTE: dbmask points to &em[0]911*/912dblen = (emlen - hlen - 1);913pslen = (dblen - saltlen - 1); /* padding string PS len */914ret = _mgf1(h, hlen, dbmask, dblen, mgf_hash_type); EG(ret, err);915916/*917* maskedb = (PS || 0x01 || salt) xor dbmask. We compute maskeddb directly918* in dbmask.919*/920921/* 1) PS is made of 0 so xoring it with first pslen bytes of dbmask is a NOP */922923/*924* 2) the byte after padding string is 0x01. Do the xor with the associated925* byte in dbmask926*/927dbmask[pslen] ^= 0x01;928929/* 3) xor the salt with the end of dbmask */930for (i = 0; i < saltlen; i++){931dbmask[dblen - saltlen + i] ^= salt[i];932}933934/* Set the leftmost 8emLen - emBits bits of the leftmost octet935* in maskedDB to zero.936*/937mask = 0;938for(i = 0; i < (8 - ((8*emlen) - embits)); i++){939mask = (u8)(mask | (0x1 << i));940}941dbmask[0] &= mask;942/* EM = maskedDB || H || 0xbc */943ret = local_memcpy(&em[dblen], h, hlen); EG(ret, err);944em[emlen - 1] = 0xbc;945(*eminlen) = (u16)emlen;946947err:948return ret;949}950951/* EMSA-PSS-VERIFY verification as described in RFC 8017 section 9.1.2952* NOTE: we enforce MGF1 as a mask generation function953*/954int emsa_pss_verify(const u8 *m, u32 mlen, const u8 *em,955u32 embits, u16 emlen,956gen_hash_alg_type gen_hash_type, gen_hash_alg_type mgf_hash_type,957u32 saltlen)958{959int ret, cmp;960u8 hlen, block_size;961u8 mhash[MAX_DIGEST_SIZE];962u8 h_[MAX_DIGEST_SIZE];963u8 zeroes[8];964const u8 *input[2] = { m, NULL };965u32 ilens[2] = { mlen, 0 };966unsigned int i;967u8 mask;968u16 _emlen;969/*970* NOTE: the NN_USABLE_MAX_BYTE_LEN should be a reasonable size here.971*/972u8 dbmask[NN_USABLE_MAX_BYTE_LEN];973u8 *db;974const u8 *h, *salt, *maskeddb = em;975u32 dblen;976const u8 *input_[4];977u32 ilens_[4];978979/* Zeroize local variables */980ret = local_memset(mhash, 0, sizeof(mhash)); EG(ret, err);981ret = local_memset(h_, 0, sizeof(h_)); EG(ret, err);982ret = local_memset(dbmask, 0, sizeof(dbmask)); EG(ret, err);983ret = local_memset(zeroes, 0, sizeof(zeroes)); EG(ret, err);984ret = local_memset(input_, 0, sizeof(input_)); EG(ret, err);985ret = local_memset(ilens_, 0, sizeof(ilens_)); EG(ret, err);986987/* Sanity checks */988MUST_HAVE((m != NULL) && (em != NULL), ret, err);989990/* Get the used hash information */991ret = gen_hash_get_hash_sizes(gen_hash_type, &hlen, &block_size); EG(ret, err);992MUST_HAVE((hlen <= MAX_DIGEST_SIZE), ret, err);993994/* Let mHash = Hash(M), an octet string of length hLen */995ret = gen_hash_hfunc_scattered(input, ilens, mhash, gen_hash_type); EG(ret, err);996997/* emBits at least 8hLen + 8sLen + 9 */998MUST_HAVE((embits >= ((8*(u32)hlen) + (8*(u32)saltlen) + 9)), ret, err);9991000/* Check that emLen == \ceil(emBits/8) */1001MUST_HAVE((((embits / 8) + 1) < (u32)((u32)0x1 << 16)), ret, err);1002_emlen = ((embits % 8) == 0) ? (u16)(embits / 8) : (u16)((embits / 8) + 1);1003MUST_HAVE((_emlen == emlen), ret, err);10041005/* If emLen < hLen + sLen + 2, output "inconsistent" and stop */1006MUST_HAVE((emlen >= ((u32)hlen + (u32)saltlen + 2)), ret, err);10071008/* If the rightmost octet of EM does not have hexadecimal value 0xbc, output "inconsistent" and stop */1009MUST_HAVE((em[emlen - 1] == 0xbc), ret, err);10101011/* If the leftmost 8emLen - emBits bits of the leftmost octet in maskedDB are not all equal to zero,1012* output "inconsistent" and stop1013* NOTE: maskeddb points to &em[0]1014*/1015mask = 0;1016for(i = 0; i < (8 - ((unsigned int)(8*emlen) - embits)); i++){1017mask = (u8)(mask | (0x1 << i));1018}1019MUST_HAVE(((maskeddb[0] & (~mask)) == 0), ret, err);10201021/* dbMask = MGF(H, emLen - hLen - 1) */1022dblen = (u32)(emlen - hlen - 1);1023h = &em[dblen];1024MUST_HAVE(((u16)dblen <= sizeof(dbmask)), ret, err); /* sanity check for overflow */1025ret = _mgf1(h, hlen, dbmask, dblen, mgf_hash_type); EG(ret, err);1026/* DB = maskedDB \xor dbMask */1027db = &dbmask[0];1028for(i = 0; i < (u16)dblen; i++){1029db[i] = (dbmask[i] ^ maskeddb[i]);1030}1031/* Set the leftmost 8emLen - emBits bits of the leftmost octet in DB to zero */1032db[0] &= mask;10331034/*1035* If the emLen - hLen - sLen - 2 leftmost octets of DB are not1036* zero or if the octet at position emLen - hLen - sLen - 1 (the1037* leftmost position is "position 1") does not have hexadecimal1038* value 0x01, output "inconsistent" and stop.1039*/1040for(i = 0; i < (u16)(dblen - saltlen - 1); i++){1041MUST_HAVE((db[i] == 0x00), ret, err);1042}1043MUST_HAVE((db[dblen - saltlen - 1] == 0x01), ret, err);10441045/* Let salt be the last sLen octets of DB */1046salt = &db[dblen - saltlen];1047/*1048* Let H' = Hash(M'), an octet string of length hLen with1049* M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt1050*/1051/* Fill input_ */1052input_[0] = zeroes;1053input_[1] = mhash;1054input_[2] = salt;1055input_[3] = NULL;1056/* Fill ilens_ */1057ilens_[0] = sizeof(zeroes);1058ilens_[1] = hlen;1059ilens_[2] = saltlen;1060ilens_[3] = 0;1061/* Hash */1062ret = gen_hash_hfunc_scattered(input_, ilens_, h_, gen_hash_type); EG(ret, err);10631064/* If H = H', output "consistent". Otherwise, output "inconsistent" */1065ret = are_equal(h, h_, hlen, &cmp); EG(ret, err);1066if(!cmp){1067ret = -1;1068}10691070err:1071return ret;1072}10731074/* EMSA-PKCS1-v1_5 encoding as described in RFC 8017 section 9.21075*/1076int emsa_pkcs1_v1_5_encode(const u8 *m, u32 mlen, u8 *em, u16 emlen,1077gen_hash_alg_type gen_hash_type)1078{1079int ret;1080const u8 *input[2] = { m, NULL };1081u32 ilens[2] = { mlen, 0 };1082u8 digest_size, block_size;1083u8 digest[MAX_DIGEST_SIZE];1084u32 digestinfo_len = 0;1085u32 tlen = 0;10861087/* Zeroize local variables */1088ret = local_memset(digest, 0, sizeof(digest)); EG(ret, err);10891090/* Compute H = Hash(M) */1091ret = gen_hash_get_hash_sizes(gen_hash_type, &digest_size, &block_size); EG(ret, err);1092MUST_HAVE((digest_size <= MAX_DIGEST_SIZE), ret, err);1093ret = gen_hash_hfunc_scattered(input, ilens, digest, gen_hash_type); EG(ret, err);10941095/* Now encode:1096*1097* DigestInfo ::= SEQUENCE {1098* digestAlgorithm AlgorithmIdentifier,1099* digest OCTET STRING1100* }1101*/1102digestinfo_len = emlen;1103/* NOTE: the rsa_digestinfo_from_hash returns the size of DigestInfo *WITHOUT* the1104* appended raw hash, tlen is the real size of the complete encoded DigestInfo.1105*/1106ret = rsa_digestinfo_from_hash(gen_hash_type, em, &digestinfo_len); EG(ret, err);1107tlen = (digestinfo_len + digest_size);11081109/* If emLen < tLen + 11, output "intended encoded message length too short" and stop */1110MUST_HAVE((emlen >= (tlen + 11)), ret, err);11111112/* Copy T at the end of em */1113digestinfo_len = emlen;1114ret = rsa_digestinfo_from_hash(gen_hash_type, &em[emlen - tlen], &digestinfo_len); EG(ret, err);1115ret = local_memcpy(&em[emlen - tlen + digestinfo_len], digest, digest_size); EG(ret, err);11161117/*1118* Format 0x00 || 0x01 || PS || 0x00 before1119*/1120em[0] = 0x00;1121em[1] = 0x01;1122em[emlen - tlen - 1] = 0x00;1123ret = local_memset(&em[2], 0xff, emlen - tlen - 3);11241125err:1126return ret;1127}11281129/****************************************************************/1130/******** Encryption schemes *************************************/1131/* The RSAES-PKCS1-V1_5-ENCRYPT algorithm as described in RFC 8017 section 7.2.11132*1133*/1134int rsaes_pkcs1_v1_5_encrypt(const rsa_pub_key *pub, const u8 *m, u32 mlen,1135u8 *c, u32 *clen, u32 modbits,1136const u8 *forced_seed, u32 seedlen)1137{1138int ret;1139u32 k;1140u8 *em = c;1141unsigned int i;1142nn m_, c_;1143m_.magic = c_.magic = WORD(0);11441145MUST_HAVE((clen != NULL) && (c != NULL) && (m != NULL), ret, err);11461147k = BYTECEIL(modbits);11481149/* Check on lengths */1150MUST_HAVE((k >= 11), ret, err);1151MUST_HAVE((mlen <= (k - 11)), ret, err);1152MUST_HAVE(((*clen) >= k), ret, err);11531154/* EME-PKCS1-v1_5 encoding EM = 0x00 || 0x02 || PS || 0x00 || M */1155em[0] = 0x00;1156em[1] = 0x02;1157if(forced_seed == NULL){1158for(i = 0; i < (k - mlen - 3); i++){1159u8 rand_byte = 0;1160while (!rand_byte) {1161ret = get_random(&rand_byte, 1); EG(ret, err);1162}1163em[2 + i] = rand_byte;1164}1165}1166else{1167MUST_HAVE((seedlen == (k - mlen - 3)), ret, err);1168/* Check that the forced seed does not contain 0x00 */1169for(i = 0; i < seedlen; i++){1170MUST_HAVE((forced_seed[i] != 0), ret, err);1171}1172ret = local_memcpy(&em[2], forced_seed, seedlen); EG(ret, err);1173}1174em[k - mlen - 1] = 0x00;1175ret = local_memcpy(&em[k - mlen], m, mlen); EG(ret, err);11761177/* RSA encryption */1178/* m = OS2IP (EM) */1179MUST_HAVE((k < (u32)((u32)0x1 << 16)), ret, err);1180ret = rsa_os2ip(&m_, em, (u16)k); EG(ret, err);1181/* c = RSAEP ((n, e), m) */1182ret = rsaep(pub, &m_, &c_); EG(ret, err);1183/* C = I2OSP (c, k) */1184ret = rsa_i2osp(&c_, c, (u16)k); EG(ret, err);1185(*clen) = (u16)k;11861187err:1188nn_uninit(&m_);1189nn_uninit(&c_);1190/* Zeroify in case of error */1191if(ret && (clen != NULL)){1192IGNORE_RET_VAL(local_memset(c, 0, (*clen)));1193}11941195return ret;1196}11971198/* The RSAES-PKCS1-V1_5-DECRYPT algorithm as described in RFC 8017 section 7.2.21199*1200*/1201ATTRIBUTE_WARN_UNUSED_RET static int _rsaes_pkcs1_v1_5_decrypt(const rsa_priv_key *priv, const rsa_pub_key *pub, const u8 *c, u32 clen,1202u8 *m, u32 *mlen, u32 modbits)1203{1204int ret;1205unsigned int i, pos;1206u32 k;1207u8 r;1208u8 *em = m;1209nn m_, c_;1210m_.magic = c_.magic = WORD(0);12111212MUST_HAVE((mlen != NULL) && (c != NULL) && (m != NULL), ret, err);12131214k = BYTECEIL(modbits);12151216/* Check on lengths */1217MUST_HAVE((clen == k) && (k >= 11), ret, err);1218MUST_HAVE(((*mlen) >= k), ret, err);12191220/* RSA decryption */1221/* c = OS2IP (C) */1222ret = rsa_os2ip(&c_, c, clen); EG(ret, err);1223/* m = RSADP ((n, d), c) */1224if(pub != NULL){1225ret = rsadp_hardened(priv, pub, &c_, &m_); EG(ret, err);1226}1227else{1228ret = rsadp(priv, &c_, &m_); EG(ret, err);1229}1230/* EM = I2OSP (m, k) */1231MUST_HAVE((k < (u32)((u32)0x1 << 16)), ret, err);1232ret = rsa_i2osp(&m_, em, (u16)k); EG(ret, err);12331234/* EME-PKCS1-v1_5 decoding: EM = 0x00 || 0x02 || PS || 0x00 || M */1235/* NOTE: we try our best to do the following in constant time to1236* limit padding oracles here (see Bleichenbacher attacks).1237*/1238ret = (1 - (!!(em[0] == 0x00) & !!(em[1] == 0x02)));1239pos = 0;1240/* Handle the first zero octet after PS in constant time */1241for(i = 2; i < k; i++){1242unsigned int mask = !!(em[i] == 0x00) & !!(pos == 0);1243pos = (mask * i) + ((1 - mask) * pos);1244}1245ret |= !(pos >= (2 + 8)); /* PS length is at least 8 (also implying we found a 0x00) */1246pos = (pos == 0) ? pos : (pos + 1);1247/* We get a random value between 2 and k if we have an error so that1248* we put a random value in pos.1249*/1250ret |= get_random((u8*)&i, 4);1251/* Get a random value r for later loop dummy operations */1252ret |= get_random(&r, 1);1253/* Update pos with random value in case of error to progress1254* nominally with the algorithm1255*/1256pos = (ret) ? ((i % (k - 2)) + 2) : pos;1257for(i = 2; i < k; i++){1258u8 r_;1259unsigned int idx;1260/* Replace m by a random value in case of error */1261idx = ((i < pos) ? 0x00 : (i - pos));1262r ^= (u8)i;1263r_ = (u8)((u8)(!!ret) * r);1264m[idx] = (em[i] ^ r_);1265}1266(*mlen) = (u16)(k - pos);1267/* Hide return value details to avoid information leak */1268ret = -(!!ret);12691270err:1271nn_uninit(&m_);1272nn_uninit(&c_);12731274return ret;1275}12761277/*1278* Basic version without much SCA/faults protections.1279*/1280int rsaes_pkcs1_v1_5_decrypt(const rsa_priv_key *priv, const u8 *c, u32 clen,1281u8 *m, u32 *mlen, u32 modbits)1282{1283return _rsaes_pkcs1_v1_5_decrypt(priv, NULL, c, clen, m, mlen, modbits);1284}12851286/*1287* Hardened version with some SCA/faults protections.1288*/1289int rsaes_pkcs1_v1_5_decrypt_hardened(const rsa_priv_key *priv, const rsa_pub_key *pub, const u8 *c, u32 clen,1290u8 *m, u32 *mlen, u32 modbits)1291{1292return _rsaes_pkcs1_v1_5_decrypt(priv, pub, c, clen, m, mlen, modbits);1293}12941295/* The RSAES-OAEP-ENCRYPT algorithm as described in RFC 8017 section 7.1.11296*1297*/1298int rsaes_oaep_encrypt(const rsa_pub_key *pub, const u8 *m, u32 mlen,1299u8 *c, u32 *clen, u32 modbits, const u8 *label, u32 label_len,1300gen_hash_alg_type gen_hash_type, gen_hash_alg_type mgf_hash_type,1301const u8 *forced_seed, u32 seedlen)1302{1303int ret;1304u32 k, pslen, khlen;1305unsigned int i;1306u8 hlen, block_size;1307u8 *em = c;1308/* Reasonable sizes */1309u8 seed[MAX_DIGEST_SIZE];1310/*1311* NOTE: the NN_USABLE_MAX_BYTE_LEN should be a reasonable size here.1312*/1313u8 dbmask[NN_USABLE_MAX_BYTE_LEN];1314u8 db[NN_USABLE_MAX_BYTE_LEN];1315u8 *seedmask = dbmask, *maskedseed = NULL, *maskeddb = NULL;1316const u8 *input[2] = { c, NULL };1317u32 ilens[2] = { 0, 0 };1318nn m_, c_;1319m_.magic = c_.magic = WORD(0);13201321/* Zeroize local variables */1322ret = local_memset(seed, 0, sizeof(seed)); EG(ret, err);1323ret = local_memset(db, 0, sizeof(db)); EG(ret, err);1324ret = local_memset(dbmask, 0, sizeof(dbmask)); EG(ret, err);13251326MUST_HAVE((clen != NULL) && (c != NULL) && (m != NULL), ret, err);13271328k = BYTECEIL(modbits);13291330ret = gen_hash_get_hash_sizes(gen_hash_type, &hlen, &block_size); EG(ret, err);1331MUST_HAVE((hlen <= MAX_DIGEST_SIZE), ret, err);13321333/* Check on lengths */1334MUST_HAVE(((u32)k >= ((2 * (u32)hlen) + 2)), ret, err);1335MUST_HAVE(((mlen ) <= ((u32)k - (2 * (u32)hlen) - 2)), ret, err);1336MUST_HAVE(((*clen) >= k), ret, err);13371338/* EME-OAEP encoding: DB = lHash || PS || 0x01 || M */1339/* and then EM = 0x00 || maskedSeed || maskedDB */1340maskedseed = &em[1];1341maskeddb = &em[hlen + 1];1342MUST_HAVE(((k - hlen - 1) <= sizeof(db)), ret, err);1343if(label == NULL){1344MUST_HAVE((label_len == 0), ret, err);1345}1346else{1347input[0] = label;1348ilens[0] = label_len;1349}1350ret = gen_hash_hfunc_scattered(input, ilens, &db[0], gen_hash_type); EG(ret, err);1351/*1352* 2.b. Generate a padding string PS consisting of k - mLen - 2hLen -1353* 2 zero octets. The length of PS may be zero.1354*1355* DB = lHash || PS || 0x01 || M. Hence, PS starts at octet hlen in DB1356*/1357pslen = (k - mlen - (u32)(2 * hlen) - 2);1358for(i = 0; i < pslen; i++){1359db[hlen + i] = 0x00;1360}1361/* 0x01 || M */1362db[hlen + pslen] = 0x01;1363for(i = 0 ; i < mlen; i++){1364db[hlen + pslen + 1 + i] = m[i];1365}1366/* Generate a random octet string seed of length hLen */1367MUST_HAVE((hlen <= sizeof(seed)), ret, err);1368if(forced_seed != NULL){1369MUST_HAVE((seedlen == hlen), ret, err);1370ret = local_memcpy(seed, forced_seed, seedlen); EG(ret, err);1371}1372else{1373ret = get_random(seed, hlen); EG(ret, err);1374}1375/* Let dbMask = MGF(seed, k - hLen - 1)*/1376khlen = (k - hlen - 1);1377MUST_HAVE((khlen <= sizeof(dbmask)), ret, err);1378ret = _mgf1(seed, hlen, dbmask, khlen, mgf_hash_type); EG(ret, err);1379/* Let maskedDB = DB \xor dbMask */1380for(i = 0; i < khlen; i++){1381maskeddb[i] = (db[i] ^ dbmask[i]);1382}1383/* Let seedMask = MGF(maskedDB, hLen) */1384MUST_HAVE((khlen < (u32)((u32)0x1 << 16)), ret, err);1385ret = _mgf1(maskeddb, (u16)khlen, seedmask, hlen, mgf_hash_type); EG(ret, err);1386/* Let maskedSeed = seed \xor seedMask */1387for(i = 0; i < hlen; i++){1388maskedseed[i] = (seed[i] ^ seedmask[i]);1389}1390/* EM = 0x00 || maskedSeed || maskedDB should be filled */1391em[0] = 0x00;13921393/* RSA encryption */1394/* m = OS2IP (EM) */1395MUST_HAVE((k < (u32)((u32)0x1 << 16)), ret, err);1396ret = rsa_os2ip(&m_, em, (u16)k); EG(ret, err);1397/* c = RSAEP ((n, e), m) */1398ret = rsaep(pub, &m_, &c_); EG(ret, err);1399/* C = I2OSP (c, k) */1400ret = rsa_i2osp(&c_, c, (u16)k); EG(ret, err);1401(*clen) = (u16)k;14021403err:1404nn_uninit(&m_);1405nn_uninit(&c_);1406/* Zeroify in case of error */1407if(ret && (clen != NULL)){1408IGNORE_RET_VAL(local_memset(c, 0, (*clen)));1409}14101411return ret;1412}14131414/* The RSAES-OAEP-DECRYPT algorithm as described in RFC 8017 section 7.1.21415*1416*/1417ATTRIBUTE_WARN_UNUSED_RET static int _rsaes_oaep_decrypt(const rsa_priv_key *priv, const rsa_pub_key *pub, const u8 *c, u32 clen,1418u8 *m, u32 *mlen, u32 modbits,1419const u8 *label, u32 label_len, gen_hash_alg_type gen_hash_type,1420gen_hash_alg_type mgf_hash_type)1421{1422int ret, cmp;1423u32 k, khlen;1424unsigned int i, pos;1425u8 hlen, block_size;1426u8 *em = m;1427u8 r;1428/* Reasonable sizes */1429u8 lhash[MAX_DIGEST_SIZE];1430u8 seedmask[MAX_DIGEST_SIZE];1431/*1432* NOTE: the NN_USABLE_MAX_BYTE_LEN should be a reasonable size here.1433*/1434u8 dbmask[NN_USABLE_MAX_BYTE_LEN];1435u8 *seed = seedmask, *maskedseed = NULL, *maskeddb = NULL, *db = NULL;1436const u8 *input[2] = { c, NULL };1437u32 ilens[2] = { 0, 0 };1438nn m_, c_;1439m_.magic = c_.magic = WORD(0);14401441/* Zeroize local variables */1442ret = local_memset(lhash, 0, sizeof(lhash)); EG(ret, err);1443ret = local_memset(seedmask, 0, sizeof(seedmask)); EG(ret, err);1444ret = local_memset(dbmask, 0, sizeof(dbmask)); EG(ret, err);14451446MUST_HAVE((c != NULL) && (m != NULL), ret, err);14471448k = BYTECEIL(modbits);14491450ret = gen_hash_get_hash_sizes(gen_hash_type, &hlen, &block_size); EG(ret, err);1451MUST_HAVE((hlen <= MAX_DIGEST_SIZE), ret, err);14521453/* Check on lengths */1454MUST_HAVE((clen == k), ret, err);1455MUST_HAVE(((u32)k >= ((2 * (u32)hlen) + 2)), ret, err);14561457/* RSA decryption */1458/* c = OS2IP (C) */1459ret = rsa_os2ip(&c_, c, clen); EG(ret, err);1460/* m = RSADP ((n, d), c) */1461if(pub != NULL){1462ret = rsadp_hardened(priv, pub, &c_, &m_); EG(ret, err);1463}1464else{1465ret = rsadp(priv, &c_, &m_); EG(ret, err);1466}1467/* EM = I2OSP (m, k) */1468MUST_HAVE((k < (u32)((u32)0x1 << 16)), ret, err);1469ret = rsa_i2osp(&m_, em, (u16)k); EG(ret, err);14701471/* EME-OAEP decoding */1472/* lHash = Hash(L) */1473if(label == NULL){1474MUST_HAVE((label_len == 0), ret, err);1475}1476else{1477input[0] = label;1478ilens[0] = label_len;1479}1480ret = gen_hash_hfunc_scattered(input, ilens, lhash, gen_hash_type); EG(ret, err);1481/* EM = Y || maskedSeed || maskedDB */1482maskedseed = &em[1];1483maskeddb = &em[hlen + 1];1484/* seedMask = MGF(maskedDB, hLen) */1485khlen = (k - hlen - 1);1486MUST_HAVE((khlen < (u32)((u32)0x1 << 16)), ret, err);1487ret = _mgf1(maskeddb, (u16)khlen, seedmask, hlen, mgf_hash_type); EG(ret, err);1488/* Let maskedSeed = seed \xor seedMask */1489for(i = 0; i < hlen; i++){1490seed[i] = (maskedseed[i] ^ seedmask[i]);1491}1492/* dbMask = MGF(seed, k - hLen - 1) */1493MUST_HAVE((khlen <= sizeof(dbmask)), ret, err);1494ret = _mgf1(seed, hlen, dbmask, khlen, mgf_hash_type); EG(ret, err);1495/* Let DB = maskedDB \xor dbMask */1496db = dbmask;1497for(i = 0; i < khlen; i++){1498db[i] = (maskeddb[i] ^ dbmask[i]);1499}1500/* DB = lHash' || PS || 0x01 || M */1501/* NOTE: we try our best to do the following in constant time to1502* limit padding oracles here (see Manger attacks).1503*/1504/* Y must be != 0 */1505ret = em[0];1506/* Isolate and compare lHash' to lHash */1507ret |= are_equal(&db[0], lhash, hlen, &cmp);1508ret |= ((~cmp) & 0x1);1509/* Find 0x01 separator in constant time */1510pos = 0;1511for(i = hlen; i < khlen; i++){1512u8 r_;1513pos = ((db[i] == 0x01) && (pos == 0)) ? i : pos;1514r_ = (pos == 0) ? db[i] : 0;1515ret |= r_; /* Capture non zero PS */1516}1517pos = (pos == 0) ? pos : (pos + 1);1518/* We get a random value between 2 and k if we have an error so that1519* we put a random value in pos.1520*/1521ret |= get_random((u8*)&i, 4);1522/* Get a random value r for later loop dummy operations */1523ret |= get_random(&r, 1);1524/* Update pos with random value in case of error to progress1525* nominally with the algorithm1526*/1527pos = (ret) ? ((i % (khlen - hlen)) + hlen) : pos;1528/* Copy the result */1529for(i = hlen; i < khlen; i++){1530u8 r_;1531unsigned int idx;1532/* Replace m by a random value in case of error */1533idx = (i < pos) ? 0x00 : (i - pos);1534r ^= (u8)i;1535r_ = (u8)((u8)(!!ret) * r);1536m[idx] = (db[i] ^ r_);1537}1538(*mlen) = (u16)(k - hlen - 1 - pos);1539/* Hide return value details to avoid information leak */1540ret = -(!!ret);15411542err:1543nn_uninit(&m_);1544nn_uninit(&c_);15451546return ret;1547}15481549/*1550* Basic version without much SCA/faults protections.1551*/1552int rsaes_oaep_decrypt(const rsa_priv_key *priv, const u8 *c, u32 clen,1553u8 *m, u32 *mlen, u32 modbits,1554const u8 *label, u32 label_len, gen_hash_alg_type gen_hash_type,1555gen_hash_alg_type mgf_hash_type)1556{1557return _rsaes_oaep_decrypt(priv, NULL, c, clen, m, mlen, modbits, label, label_len, gen_hash_type, mgf_hash_type);1558}15591560/*1561* Hardened version with some SCA/faults protections.1562*/1563int rsaes_oaep_decrypt_hardened(const rsa_priv_key *priv, const rsa_pub_key *pub, const u8 *c, u32 clen,1564u8 *m, u32 *mlen, u32 modbits,1565const u8 *label, u32 label_len, gen_hash_alg_type gen_hash_type,1566gen_hash_alg_type mgf_hash_type)1567{1568return _rsaes_oaep_decrypt(priv, pub, c, clen, m, mlen, modbits, label, label_len, gen_hash_type, mgf_hash_type);1569}15701571/****************************************************************/1572/******** Signature schemes *************************************/1573/* The RSASSA-PKCS1-V1_5-SIGN signature algorithm as described in RFC 8017 section 8.2.11574*1575*/1576ATTRIBUTE_WARN_UNUSED_RET static int _rsassa_pkcs1_v1_5_sign(const rsa_priv_key *priv, const rsa_pub_key *pub, const u8 *m, u32 mlen,1577u8 *s, u16 *slen, u32 modbits, gen_hash_alg_type gen_hash_type)1578{1579int ret;1580u8 *em = s;1581u32 k;1582nn m_, s_;1583m_.magic = s_.magic = WORD(0);15841585/* Checks on sizes */1586MUST_HAVE((slen != NULL), ret, err);15871588k = BYTECEIL(modbits);15891590/* Only accept reasonable sizes */1591MUST_HAVE((k < (u32)((u32)0x1 << 16)), ret, err);1592/* Sanity check on size */1593MUST_HAVE(((*slen) >= k), ret, err);15941595/* EM = EMSA-PKCS1-V1_5-ENCODE (M, k) */1596ret = emsa_pkcs1_v1_5_encode(m, mlen, em, (u16)k, gen_hash_type); EG(ret, err);15971598/* m = OS2IP (EM) */1599ret = rsa_os2ip(&m_, em, (u16)k); EG(ret, err);1600/* s = RSASP1 (K, m) */1601if(pub != NULL){1602ret = rsasp1_hardened(priv, pub, &m_, &s_); EG(ret, err);1603}1604else{1605ret = rsasp1(priv, &m_, &s_); EG(ret, err);1606}1607/* S = I2OSP (s, k) */1608ret = rsa_i2osp(&s_, s, (u16)k);1609(*slen) = (u16)k;16101611err:1612nn_uninit(&m_);1613nn_uninit(&s_);1614/* Zeroify in case of error */1615if(ret && (slen != NULL)){1616IGNORE_RET_VAL(local_memset(s, 0, (*slen)));1617}16181619return ret;1620}16211622/*1623* Basic version without much SCA/faults protections.1624*/1625int rsassa_pkcs1_v1_5_sign(const rsa_priv_key *priv, const u8 *m, u32 mlen,1626u8 *s, u16 *slen, u32 modbits, gen_hash_alg_type gen_hash_type)1627{1628return _rsassa_pkcs1_v1_5_sign(priv, NULL, m, mlen, s, slen, modbits, gen_hash_type);1629}16301631/*1632* Hardened version with some SCA/faults protections.1633*/1634int rsassa_pkcs1_v1_5_sign_hardened(const rsa_priv_key *priv, const rsa_pub_key *pub, const u8 *m, u32 mlen,1635u8 *s, u16 *slen, u32 modbits, gen_hash_alg_type gen_hash_type)1636{1637return _rsassa_pkcs1_v1_5_sign(priv, pub, m, mlen, s, slen, modbits, gen_hash_type);1638}16391640/* The RSASSA-PKCS1-V1_5-VERIFY verification algorithm as described in RFC 8017 section 8.2.21641*1642*/1643int rsassa_pkcs1_v1_5_verify(const rsa_pub_key *pub, const u8 *m, u32 mlen,1644const u8 *s, u16 slen, u32 modbits, gen_hash_alg_type gen_hash_type)1645{1646int ret, cmp;1647/* Get a large enough buffer to hold the result */1648/*1649* NOTE: the NN_USABLE_MAX_BYTE_LEN should be a reasonable size here.1650*/1651u8 em[NN_USABLE_MAX_BYTE_LEN];1652u8 em_[NN_USABLE_MAX_BYTE_LEN];1653u32 k;1654nn m_, s_;1655m_.magic = s_.magic = WORD(0);16561657/* Zeroize local variables */1658ret = local_memset(em, 0, sizeof(em)); EG(ret, err);1659ret = local_memset(em_, 0, sizeof(em_)); EG(ret, err);16601661k = BYTECEIL(modbits);1662/* Only accept reasonable sizes */1663MUST_HAVE((k < (u32)((u32)0x1 << 16)), ret, err);16641665/* Length checking: If the length of the signature S is not k1666* octets, output "invalid signature" and stop.1667*/1668MUST_HAVE(((u16)k == slen), ret, err);16691670/* s = OS2IP (S) */1671ret = rsa_os2ip(&s_, s, slen); EG(ret, err);1672/* m = RSAVP1 ((n, e), s) */1673ret = rsavp1(pub, &s_, &m_); EG(ret, err);1674/* EM = I2OSP (m, k) */1675MUST_HAVE((slen <= sizeof(em)), ret, err);1676ret = rsa_i2osp(&m_, em, slen); EG(ret, err);1677/* EM' = EMSA-PKCS1-V1_5-ENCODE (M, k) */1678MUST_HAVE((k <= sizeof(em_)), ret, err);1679ret = emsa_pkcs1_v1_5_encode(m, mlen, em_, (u16)k, gen_hash_type); EG(ret, err);16801681/* Compare */1682ret = are_equal(em, em_, (u16)k, &cmp); EG(ret, err);1683if(!cmp){1684ret = -1;1685}1686err:1687nn_uninit(&m_);1688nn_uninit(&s_);16891690return ret;1691}16921693/* The RSASSA-PSS-SIGN signature algorithm as described in RFC 8017 section 8.1.11694*1695*/1696ATTRIBUTE_WARN_UNUSED_RET static int _rsassa_pss_sign(const rsa_priv_key *priv, const rsa_pub_key *pub, const u8 *m, u32 mlen,1697u8 *s, u16 *slen, u32 modbits,1698gen_hash_alg_type gen_hash_type, gen_hash_alg_type mgf_hash_type,1699u32 saltlen, const u8 *forced_salt)1700{1701int ret;1702u8 *em = s;1703u16 emsize;1704u32 k;1705nn m_, s_;1706m_.magic = s_.magic = WORD(0);17071708MUST_HAVE((slen != NULL), ret, err);17091710MUST_HAVE((modbits > 1), ret, err);17111712k = BYTECEIL(modbits);1713MUST_HAVE((k < (u32)((u32)0x1 << 16)), ret, err);17141715/* Sanity check on size */1716MUST_HAVE(((*slen) >= k), ret, err);17171718/* EM = EMSA-PSS-ENCODE (M, modBits - 1) */1719emsize = (*slen);1720ret = emsa_pss_encode(m, mlen, em, (modbits - 1), &emsize, gen_hash_type, mgf_hash_type, saltlen, forced_salt); EG(ret, err);17211722/* Note that the octet length of EM will be one less than k if modBits - 1 is divisible by 8 and equal to k otherwise */1723MUST_HAVE(emsize == BYTECEIL(modbits - 1), ret, err);17241725/* m = OS2IP (EM) */1726ret = rsa_os2ip(&m_, em, (u16)emsize); EG(ret, err);1727/* s = RSASP1 (K, m) */1728if(pub != NULL){1729ret = rsasp1_hardened(priv, pub, &m_, &s_); EG(ret, err);1730}1731else{1732ret = rsasp1(priv, &m_, &s_); EG(ret, err);1733}1734/* S = I2OSP (s, k) */1735MUST_HAVE((k < ((u32)0x1 << 16)), ret, err);1736ret = rsa_i2osp(&s_, s, (u16)k);1737(*slen) = (u16)k;17381739err:1740nn_uninit(&m_);1741nn_uninit(&s_);1742/* Zeroify in case of error */1743if(ret && (slen != NULL)){1744IGNORE_RET_VAL(local_memset(s, 0, (*slen)));1745}17461747return ret;1748}17491750/*1751* Basic version without much SCA/faults protections.1752*/1753int rsassa_pss_sign(const rsa_priv_key *priv, const u8 *m, u32 mlen,1754u8 *s, u16 *slen, u32 modbits,1755gen_hash_alg_type gen_hash_type, gen_hash_alg_type mgf_hash_type,1756u32 saltlen, const u8 *forced_salt)1757{1758return _rsassa_pss_sign(priv, NULL, m, mlen, s, slen, modbits, gen_hash_type, mgf_hash_type, saltlen, forced_salt);1759}17601761/*1762* Hardened version with some SCA/faults protections.1763*/1764int rsassa_pss_sign_hardened(const rsa_priv_key *priv, const rsa_pub_key *pub, const u8 *m, u32 mlen,1765u8 *s, u16 *slen, u32 modbits,1766gen_hash_alg_type gen_hash_type, gen_hash_alg_type mgf_hash_type,1767u32 saltlen, const u8 *forced_salt)1768{1769return _rsassa_pss_sign(priv, pub, m, mlen, s, slen, modbits, gen_hash_type, mgf_hash_type, saltlen, forced_salt);1770}177117721773/* The RSASSA-PSS-VERIFY verification algorithm as described in RFC 8017 section 8.1.21774*1775*/1776int rsassa_pss_verify(const rsa_pub_key *pub, const u8 *m, u32 mlen,1777const u8 *s, u16 slen, u32 modbits,1778gen_hash_alg_type gen_hash_type, gen_hash_alg_type mgf_hash_type,1779u32 saltlen)1780{1781int ret;1782/* Get a large enough buffer to hold the result */1783/*1784* NOTE: the NN_USABLE_MAX_BYTE_LEN should be a reasonable size here.1785*/1786u8 em[NN_USABLE_MAX_BYTE_LEN];1787u16 emlen;1788u32 k;1789nn m_, s_;1790m_.magic = s_.magic = WORD(0);17911792/* Zeroize local variables */1793ret = local_memset(em, 0, sizeof(em)); EG(ret, err);17941795MUST_HAVE((modbits > 1), ret, err);1796k = BYTECEIL(modbits);1797MUST_HAVE((k < (u32)((u32)0x1 << 16)), ret, err);17981799/* s = OS2IP (S) */1800ret = rsa_os2ip(&s_, s, slen); EG(ret, err);1801/* m = RSAVP1 ((n, e), s) */1802ret = rsavp1(pub, &s_, &m_); EG(ret, err);1803/* emLen = \ceil ((modBits - 1)/8) */1804MUST_HAVE((((modbits - 1) / 8) + 1) < (u32)((u32)0x1 << 16), ret, err);1805emlen = (((modbits - 1) % 8) == 0) ? (u16)((modbits - 1) / 8) : (u16)(((modbits - 1) / 8) + 1);18061807/* Note that emLen will be one less than k if modBits - 1 is divisible by 8 and equal to k otherwise */1808MUST_HAVE(emlen == BYTECEIL(modbits - 1), ret, err);18091810/* EM = I2OSP (m, emLen) */1811MUST_HAVE((emlen <= sizeof(em)), ret, err);1812ret = rsa_i2osp(&m_, em, (u16)emlen); EG(ret, err);1813/* Result = EMSA-PSS-VERIFY (M, EM, modBits - 1) */1814ret = emsa_pss_verify(m, mlen, em, (modbits - 1), emlen, gen_hash_type, mgf_hash_type, saltlen);18151816err:1817nn_uninit(&m_);1818nn_uninit(&s_);18191820return ret;1821}18221823/* The RSA signature algorithm using ISO/IEC 9796-2 padding scheme 1.1824* This is a signature with recovery.1825*1826* XXX: beware that this scheme is here for completeness, but is considered fragile1827* since practical attacks exist when the hash function is of relatively "small" size1828* (see http://www.crypto-uni.lu/jscoron/publications/iso97962joc.pdf).1829*1830* The ISO/IEC 9796-2 is also described in EMV Book 2 in the A.2.1 section:1831* "Digital Signature Scheme Giving Message Recovery".1832*1833*/1834ATTRIBUTE_WARN_UNUSED_RET static int _rsa_iso9796_2_sign_recover(const rsa_priv_key *priv, const rsa_pub_key *pub,1835const u8 *m, u32 mlen, u32 *m1len, u32 *m2len, u8 *s, u16 *slen,1836u32 modbits, gen_hash_alg_type gen_hash_type)1837{1838int ret;1839u32 k, m1len_, m2len_;1840u8 hlen, block_size;1841gen_hash_context hctx;1842nn m_, s_;1843m_.magic = s_.magic = WORD(0);18441845MUST_HAVE((priv != NULL) && (m != NULL), ret, err);18461847MUST_HAVE((slen != NULL), ret, err);18481849MUST_HAVE((modbits > 1), ret, err);18501851k = BYTECEIL(modbits);1852MUST_HAVE((k < (u32)((u32)0x1 << 16)), ret, err);18531854/* Get hash parameters */1855ret = gen_hash_get_hash_sizes(gen_hash_type, &hlen, &block_size); EG(ret, err);1856MUST_HAVE((hlen <= MAX_DIGEST_SIZE), ret, err);18571858/* Sanity check on sizes */1859MUST_HAVE(((*slen) >= k), ret, err);1860MUST_HAVE(k >= (u32)(2 + hlen), ret, err);18611862/* Compute our recoverable and non-recoverable parts */1863m1len_ = (mlen >= (k - 2 - hlen)) ? (k - 2 - hlen) : mlen;1864m2len_ = (mlen - m1len_);18651866/* Now hash the message */1867ret = gen_hash_init(&hctx, gen_hash_type); EG(ret, err);1868ret = gen_hash_update(&hctx, m, mlen, gen_hash_type); EG(ret, err);1869ret = gen_hash_final(&hctx, &s[k - 1 - hlen], gen_hash_type); EG(ret, err);18701871/* Put M1 */1872ret = local_memcpy(&s[1], m, m1len_); EG(ret, err);1873if(m1len != NULL){1874(*m1len) = m1len_;1875}1876if(m2len != NULL){1877(*m2len) = m2len_;1878}18791880/* Put the constants */1881s[0] = 0x6a;1882s[k - 1] = 0xbc;18831884/* m = OS2IP (X) */1885ret = rsa_os2ip(&m_, s, k); EG(ret, err);1886/* s = RSASP1 (K, m) */1887if(pub != NULL){1888ret = rsasp1_hardened(priv, pub, &m_, &s_); EG(ret, err);1889}1890else{1891ret = rsasp1(priv, &m_, &s_); EG(ret, err);1892}1893/* S = I2OSP (s, k) */1894MUST_HAVE((k < ((u32)0x1 << 16)), ret, err);1895ret = rsa_i2osp(&s_, s, (u16)k);1896(*slen) = (u16)k;18971898err:1899nn_uninit(&m_);1900nn_uninit(&s_);19011902if(ret && (m1len != 0)){1903(*m1len) = 0;1904}1905if(ret && (m2len != 0)){1906(*m2len) = 0;1907}19081909return ret;1910}19111912/*1913* Basic version without much SCA/faults protections.1914*/1915int rsa_iso9796_2_sign_recover(const rsa_priv_key *priv, const u8 *m, u32 mlen, u32 *m1len,1916u32 *m2len, u8 *s, u16 *slen,1917u32 modbits, gen_hash_alg_type gen_hash_type)1918{1919return _rsa_iso9796_2_sign_recover(priv, NULL, m, mlen, m1len, m2len, s, slen, modbits, gen_hash_type);1920}19211922/*1923* Hardened version with some SCA/faults protections.1924*/1925int rsa_iso9796_2_sign_recover_hardened(const rsa_priv_key *priv, const rsa_pub_key *pub,1926const u8 *m, u32 mlen, u32 *m1len, u32 *m2len, u8 *s, u16 *slen,1927u32 modbits, gen_hash_alg_type gen_hash_type)1928{1929return _rsa_iso9796_2_sign_recover(priv, pub, m, mlen, m1len, m2len, s, slen, modbits, gen_hash_type);1930}19311932/* The RSA verification algorithm using ISO/IEC 9796-2 padding scheme 1.1933* This is a verification with recovery.1934*1935* XXX: beware that this scheme is here for completeness, but is considered fragile1936* since practical attacks exist when the hash function is of relatively "small" size1937* (see http://www.crypto-uni.lu/jscoron/publications/iso97962joc.pdf).1938*1939* The ISO/IEC 9796-2 is also described in EMV Book 2 in the A.2.1 section:1940* "Digital Signature Scheme Giving Message Recovery".1941*1942*/1943int rsa_iso9796_2_verify_recover(const rsa_pub_key *pub, const u8 *m2, u32 m2len, u8 *m1, u32 *m1len,1944const u8 *s, u16 slen, u32 modbits, gen_hash_alg_type gen_hash_type)1945{1946int ret, cmp;1947/* Get a large enough buffer to hold the result */1948/*1949* NOTE: the NN_USABLE_MAX_BYTE_LEN should be a reasonable size here.1950*/1951u8 X[NN_USABLE_MAX_BYTE_LEN];1952u8 H[MAX_DIGEST_SIZE];1953u32 k, m1len_;1954u8 hlen, block_size;1955gen_hash_context hctx;1956nn m_, s_;1957m_.magic = s_.magic = WORD(0);19581959MUST_HAVE((pub != NULL) && (m2 != NULL), ret, err);19601961/* Zeroize local variables */1962ret = local_memset(X, 0, sizeof(X)); EG(ret, err);1963ret = local_memset(H, 0, sizeof(H)); EG(ret, err);19641965k = BYTECEIL(modbits);1966/* Only accept reasonable sizes */1967MUST_HAVE((k < (u32)((u32)0x1 << 16)), ret, err);19681969ret = gen_hash_get_hash_sizes(gen_hash_type, &hlen, &block_size); EG(ret, err);1970MUST_HAVE((hlen <= MAX_DIGEST_SIZE), ret, err);19711972/* Length checking: If the length of the signature S is not k1973* octets, output "invalid signature" and stop.1974*/1975MUST_HAVE(((u16)k == slen), ret, err);1976MUST_HAVE((slen >= (hlen + 2)), ret, err);1977m1len_ = (u32)(slen - (hlen + 2));19781979/* s = OS2IP (S) */1980ret = rsa_os2ip(&s_, s, slen); EG(ret, err);1981/* m = RSAVP1 ((n, e), s) */1982ret = rsavp1(pub, &s_, &m_); EG(ret, err);1983/* EM = I2OSP (m, k) */1984MUST_HAVE((slen <= sizeof(X)), ret, err);1985ret = rsa_i2osp(&m_, X, slen); EG(ret, err);19861987/* Split the message in B || m1 || H || E with1988* B = '6A', E = 'BC', and H the hash value */1989if(m1len != NULL){1990MUST_HAVE((*m1len) >= m1len_, ret, err);1991(*m1len) = m1len_;1992}1993if((X[0] != 0x6a) || (X[slen - 1] != 0xbc)){1994ret = -1;1995goto err;1996}19971998/* Compute the hash of m1 || m2 */1999ret = gen_hash_init(&hctx, gen_hash_type); EG(ret, err);2000ret = gen_hash_update(&hctx, &X[1], m1len_, gen_hash_type); EG(ret, err);2001ret = gen_hash_update(&hctx, m2, m2len, gen_hash_type); EG(ret, err);2002ret = gen_hash_final(&hctx, H, gen_hash_type); EG(ret, err);20032004/* Compare */2005ret = are_equal(H, &X[1 + m1len_], (u16)hlen, &cmp); EG(ret, err);2006if(!cmp){2007ret = -1;2008}2009/* If comparison is OK, copy data */2010if(m1 != NULL){2011MUST_HAVE((m1len != NULL), ret, err);2012ret = local_memcpy(m1, &X[1], (*m1len)); EG(ret, err);2013}20142015err:2016nn_uninit(&m_);2017nn_uninit(&s_);20182019if(ret && (m1len != 0)){2020(*m1len) = 0;2021}20222023return ret;2024}20252026#ifdef RSA2027/* RSA PKCS#1 test vectors taken from:2028* https://github.com/bdauvergne/python-pkcs1/tree/master/tests/data2029*/2030#include "rsa_pkcs1_tests.h"20312032int main(int argc, char *argv[])2033{2034int ret = 0;2035FORCE_USED_VAR(argc);2036FORCE_USED_VAR(argv);20372038/* Sanity check on size for RSA.2039* NOTE: the double parentheses are here to handle -Wunreachable-code2040*/2041if((NN_USABLE_MAX_BIT_LEN) < (4096)){2042ext_printf("Error: you seem to have compiled libecc with usable NN size < 4096, not suitable for RSA.\n");2043ext_printf(" => Please recompile libecc with EXTRA_CFLAGS=\"-DUSER_NN_BIT_LEN=4096\"\n");2044ext_printf(" This will increase usable NN for proper RSA up to 4096 bits.\n");2045ext_printf(" Then recompile the current examples with the same EXTRA_CFLAGS=\"-DUSER_NN_BIT_LEN=4096\" flag and execute again!\n");2046/* NOTE: ret = 0 here to pass self tests even if the library is not compatible */2047ret = 0;2048goto err;2049}20502051ret = perform_rsa_tests(all_rsa_tests, sizeof(all_rsa_tests) / sizeof(rsa_test*));20522053err:2054return ret;2055}2056#endif205720582059