[Opentnl-cvs] tnl/libtomcrypt/pk/pkcs1 pkcs_1_i2osp.c,NONE,1.1 pkcs_1_mgf1.c,NONE,1.1 pkcs_1_oaep_de
Brought to you by:
mark_frohnmayer,
s_alanet
From: Mark F. <mar...@us...> - 2005-04-28 17:28:12
|
Update of /cvsroot/opentnl/tnl/libtomcrypt/pk/pkcs1 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26694/libtomcrypt/pk/pkcs1 Added Files: pkcs_1_i2osp.c pkcs_1_mgf1.c pkcs_1_oaep_decode.c pkcs_1_oaep_encode.c pkcs_1_os2ip.c pkcs_1_pss_decode.c pkcs_1_pss_encode.c pkcs_1_v15_es_decode.c pkcs_1_v15_es_encode.c pkcs_1_v15_sa_decode.c pkcs_1_v15_sa_encode.c Log Message: Updated to libtomcrypt 1.0.2 Not tested on linux or OS X --- NEW FILE: pkcs_1_pss_encode.c --- /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tom...@gm..., http://libtomcrypt.org */ #include "tomcrypt.h" /** @file pkcs_1_pss_encode.c PKCS #1 PSS Signature Padding, Tom St Denis */ #ifdef PKCS_1 /** PKCS #1 v2.00 Signature Encoding @param msghash The hash to encode @param msghashlen The length of the hash (octets) @param saltlen The length of the salt desired (octets) @param prng An active PRNG context @param prng_idx The index of the PRNG desired @param hash_idx The index of the hash desired @param modulus_bitlen The bit length of the RSA modulus @param out [out] The destination of the encoding @param outlen [in/out] The max size and resulting size of the encoded data @return CRYPT_OK if successful */ int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, unsigned long saltlen, prng_state *prng, int prng_idx, int hash_idx, unsigned long modulus_bitlen, unsigned char *out, unsigned long *outlen) { unsigned char *DB, *mask, *salt, *hash; unsigned long x, y, hLen, modulus_len; int err; hash_state md; LTC_ARGCHK(msghash != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* ensure hash and PRNG are valid */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { return err; } hLen = hash_descriptor[hash_idx].hashsize; modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); /* check sizes */ if ((saltlen > modulus_len) || (modulus_len < hLen + saltlen + 2)) { return CRYPT_PK_INVALID_SIZE; } /* allocate ram for DB/mask/salt/hash of size modulus_len */ DB = XMALLOC(modulus_len); mask = XMALLOC(modulus_len); salt = XMALLOC(modulus_len); hash = XMALLOC(modulus_len); if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) { if (DB != NULL) { XFREE(DB); } if (mask != NULL) { XFREE(mask); } if (salt != NULL) { XFREE(salt); } if (hash != NULL) { XFREE(hash); } return CRYPT_MEM; } /* generate random salt */ if (saltlen > 0) { if (prng_descriptor[prng_idx].read(salt, saltlen, prng) != saltlen) { err = CRYPT_ERROR_READPRNG; goto LBL_ERR; } } /* M = (eight) 0x00 || msghash || salt, hash = H(M) */ if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) { goto LBL_ERR; } zeromem(DB, 8); if ((err = hash_descriptor[hash_idx].process(&md, DB, 8)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx].process(&md, salt, saltlen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx].done(&md, hash)) != CRYPT_OK) { goto LBL_ERR; } /* generate DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */ for (x = 0; x < (modulus_len - saltlen - hLen - 2); x++) { DB[x] = 0x00; } DB[x++] = 0x01; for (y = 0; y < saltlen; y++) { DB[x++] = salt[y]; } /* generate mask of length modulus_len - hLen - 1 from hash */ if ((err = pkcs_1_mgf1(hash, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) { goto LBL_ERR; } /* xor against DB */ for (y = 0; y < (modulus_len - hLen - 1); y++) { DB[y] ^= mask[y]; } /* output is DB || hash || 0xBC */ if (*outlen < modulus_len) { err = CRYPT_BUFFER_OVERFLOW; goto LBL_ERR; } /* DB */ for (y = x = 0; x < modulus_len - hLen - 1; x++) { out[y++] = DB[x]; } /* hash */ for (x = 0; x < hLen; x++) { out[y++] = hash[x]; } /* 0xBC */ out[y] = 0xBC; /* now clear the 8*modulus_len - modulus_bitlen most significant bits */ out[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)); /* store output size */ *outlen = modulus_len; err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(DB, modulus_len); zeromem(mask, modulus_len); zeromem(salt, modulus_len); zeromem(hash, modulus_len); #endif XFREE(hash); XFREE(salt); XFREE(mask); XFREE(DB); return err; } #endif /* PKCS_1 */ --- NEW FILE: pkcs_1_v15_es_decode.c --- /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tom...@gm..., http://libtomcrypt.org */ #include "tomcrypt.h" /** @file pkcs_1_v15_es_decode.c PKCS #1 v1.5 Encryption Padding, Tom St Denis */ #ifdef PKCS_1 /** PKCS #1 v1.5 Encryption Decoding @param msg The padded data @param msglen The length of the padded data (octets) @param modulus_bitlen The bit length of the RSA modulus @param out [out] Where to store the decoded data @param outlen The length of the decoded data @param res [out] Result of the decoding, 1==valid, 0==invalid @return CRYPT_OK if successful */ int pkcs_1_v15_es_decode(const unsigned char *msg, unsigned long msglen, unsigned long modulus_bitlen, unsigned char *out, unsigned long outlen, int *res) { unsigned long x, modulus_bytelen; LTC_ARGCHK(msg != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(res != NULL); /* default to failed */ *res = 0; modulus_bytelen = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); /* must be at least modulus_bytelen bytes long */ if (msglen != modulus_bytelen) { return CRYPT_INVALID_ARG; } /* should start with 0x00 0x02 */ if (msg[0] != 0x00 || msg[1] != 0x02) { return CRYPT_OK; } /* skip over PS */ x = 2 + (modulus_bytelen - outlen - 3); /* should be 0x00 */ if (msg[x++] != 0x00) { return CRYPT_OK; } /* the message is left */ if (x + outlen > modulus_bytelen) { return CRYPT_PK_INVALID_SIZE; } XMEMCPY(out, msg + x, outlen); *res = 1; return CRYPT_OK; } #endif --- NEW FILE: pkcs_1_os2ip.c --- /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tom...@gm..., http://libtomcrypt.org */ #include "tomcrypt.h" /** @file pkcs_1_os2ip.c Octet to Integer OS2IP, Tom St Denis */ #ifdef PKCS_1 /** Read a binary string into an mp_int @param n [out] The mp_int destination @param in The binary string to read @param inlen The length of the binary string @return CRYPT_OK if successful */ int pkcs_1_os2ip(mp_int *n, unsigned char *in, unsigned long inlen) { int err; /* read it */ if ((err = mp_read_unsigned_bin(n, in, inlen)) != MP_OKAY) { return mpi_to_ltc_error(err); } return CRYPT_OK; } #endif /* PKCS_1 */ --- NEW FILE: pkcs_1_oaep_decode.c --- /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tom...@gm..., http://libtomcrypt.org */ #include "tomcrypt.h" /** @file pkcs_1_oaep_decode.c OAEP Padding for PKCS #1, Tom St Denis */ #ifdef PKCS_1 /** PKCS #1 v2.00 OAEP decode @param msg The encoded data to decode @param msglen The length of the encoded data (octets) @param lparam The session or system data (can be NULL) @param lparamlen The length of the lparam @param modulus_bitlen The bit length of the RSA modulus @param hash_idx The index of the hash desired @param out [out] Destination of decoding @param outlen [in/out] The max size and resulting size of the decoding @param res [out] Result of decoding, 1==valid, 0==invalid @return CRYPT_OK if successful (even if invalid) */ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, const unsigned char *lparam, unsigned long lparamlen, unsigned long modulus_bitlen, int hash_idx, unsigned char *out, unsigned long *outlen, int *res) { unsigned char *DB, *seed, *mask; unsigned long hLen, x, y, modulus_len; int err; LTC_ARGCHK(msg != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(res != NULL); /* default to invalid packet */ *res = 0; /* test valid hash */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } hLen = hash_descriptor[hash_idx].hashsize; modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); /* test hash/message size */ if ((2*hLen >= (modulus_len - 2)) || (msglen != modulus_len)) { return CRYPT_PK_INVALID_SIZE; } /* allocate ram for DB/mask/salt of size modulus_len */ DB = XMALLOC(modulus_len); mask = XMALLOC(modulus_len); seed = XMALLOC(modulus_len); if (DB == NULL || mask == NULL || seed == NULL) { if (DB != NULL) { XFREE(DB); } if (mask != NULL) { XFREE(mask); } if (seed != NULL) { XFREE(seed); } return CRYPT_MEM; } /* ok so it's now in the form 0x00 || maskedseed || maskedDB 1 || hLen || modulus_len - hLen - 1 */ /* must have leading 0x00 byte */ if (msg[0] != 0x00) { err = CRYPT_OK; goto LBL_ERR; } /* now read the masked seed */ for (x = 1, y = 0; y < hLen; y++) { seed[y] = msg[x++]; } /* now read the masked DB */ for (y = 0; y < modulus_len - hLen - 1; y++) { DB[y] = msg[x++]; } /* compute MGF1 of maskedDB (hLen) */ if ((err = pkcs_1_mgf1(DB, modulus_len - hLen - 1, hash_idx, mask, hLen)) != CRYPT_OK) { goto LBL_ERR; } /* XOR against seed */ for (y = 0; y < hLen; y++) { seed[y] ^= mask[y]; } /* compute MGF1 of seed (k - hlen - 1) */ if ((err = pkcs_1_mgf1(seed, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) { goto LBL_ERR; } /* xor against DB */ for (y = 0; y < (modulus_len - hLen - 1); y++) { DB[y] ^= mask[y]; } /* now DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */ /* compute lhash and store it in seed [reuse temps!] */ x = modulus_len; if (lparam != NULL) { if ((err = hash_memory(hash_idx, lparam, lparamlen, seed, &x)) != CRYPT_OK) { goto LBL_ERR; } } else { /* can't pass hash_memory a NULL so use DB with zero length */ if ((err = hash_memory(hash_idx, DB, 0, seed, &x)) != CRYPT_OK) { goto LBL_ERR; } } /* compare the lhash'es */ if (memcmp(seed, DB, hLen) != 0) { err = CRYPT_OK; goto LBL_ERR; } /* now zeroes before a 0x01 */ for (x = hLen; x < (modulus_len - hLen - 1) && DB[x] == 0x00; x++) { /* step... */ } /* error out if wasn't 0x01 */ if (x == (modulus_len - hLen - 1) || DB[x] != 0x01) { err = CRYPT_OK; goto LBL_ERR; } /* rest is the message (and skip 0x01) */ if ((modulus_len - hLen - 1) - ++x > *outlen) { err = CRYPT_BUFFER_OVERFLOW; goto LBL_ERR; } /* copy message */ *outlen = (modulus_len - hLen - 1) - x; for (y = 0; x != (modulus_len - hLen - 1); ) { out[y++] = DB[x++]; } /* valid packet */ *res = 1; err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(DB, modulus_len); zeromem(seed, modulus_len); zeromem(mask, modulus_len); #endif XFREE(seed); XFREE(mask); XFREE(DB); return err; } #endif /* PKCS_1 */ --- NEW FILE: pkcs_1_mgf1.c --- /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tom...@gm..., http://libtomcrypt.org */ #include "tomcrypt.h" /** @file pkcs_1_mgf1.c The Mask Generation Function (MGF1) for PKCS #1, Tom St Denis */ #ifdef PKCS_1 /** Perform PKCS #1 MGF1 (internal) @param seed The seed for MGF1 @param seedlen The length of the seed @param hash_idx The index of the hash desired @param mask [out] The destination @param masklen The length of the mask desired @return CRYPT_OK if successful */ int pkcs_1_mgf1(const unsigned char *seed, unsigned long seedlen, int hash_idx, unsigned char *mask, unsigned long masklen) { unsigned long hLen, x; ulong32 counter; int err; hash_state *md; unsigned char *buf; LTC_ARGCHK(seed != NULL); LTC_ARGCHK(mask != NULL); /* ensure valid hash */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } /* get hash output size */ hLen = hash_descriptor[hash_idx].hashsize; /* allocate memory */ md = XMALLOC(sizeof(hash_state)); buf = XMALLOC(hLen); if (md == NULL || buf == NULL) { if (md != NULL) { XFREE(md); } if (buf != NULL) { XFREE(buf); } return CRYPT_MEM; } /* start counter */ counter = 0; while (masklen > 0) { /* handle counter */ STORE32H(counter, buf); ++counter; /* get hash of seed || counter */ if ((err = hash_descriptor[hash_idx].init(md)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx].process(md, seed, seedlen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx].process(md, buf, 4)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx].done(md, buf)) != CRYPT_OK) { goto LBL_ERR; } /* store it */ for (x = 0; x < hLen && masklen > 0; x++, masklen--) { *mask++ = buf[x]; } } err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(buf, hLen); zeromem(md, sizeof(hash_state)); #endif XFREE(buf); XFREE(md); return err; } #endif /* PKCS_1 */ --- NEW FILE: pkcs_1_i2osp.c --- /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tom...@gm..., http://libtomcrypt.org */ #include "tomcrypt.h" /** @file pkcs_1_i2osp.c Integer to Octet I2OSP, Tom St Denis */ #ifdef PKCS_1 /* always stores the same # of bytes, pads with leading zero bytes as required */ /** PKCS #1 Integer to binary @param n The integer to store @param modulus_len The length of the RSA modulus @param out [out] The destination for the integer @return CRYPT_OK if successful */ int pkcs_1_i2osp(mp_int *n, unsigned long modulus_len, unsigned char *out) { int err; unsigned long size; size = mp_unsigned_bin_size(n); if (size > modulus_len) { return CRYPT_BUFFER_OVERFLOW; } /* store it */ zeromem(out, modulus_len); if ((err = mp_to_unsigned_bin(n, out+(modulus_len-size))) != MP_OKAY) { return mpi_to_ltc_error(err); } return CRYPT_OK; } #endif /* PKCS_1 */ --- NEW FILE: pkcs_1_v15_sa_decode.c --- /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tom...@gm..., http://libtomcrypt.org */ #include "tomcrypt.h" /** @file pkcs_1_v15_sa_decode.c PKCS #1 v1.5 Signature Padding, Tom St Denis */ #ifdef PKCS_1 /** Perform PKCS #1 v1.5 Signature Decoding @param msghash The hash that was signed @param msghashlen The length of the hash @param sig The signature [padded data] @param siglen The length of the signature @param hash_idx The index of the hash used @param modulus_bitlen The bit length of the RSA modulus @param res [out] Result of comparison, 1==valid, 0==invalid @return CRYPT_OK if successful */ int pkcs_1_v15_sa_decode(const unsigned char *msghash, unsigned long msghashlen, const unsigned char *sig, unsigned long siglen, int hash_idx, unsigned long modulus_bitlen, int *res) { unsigned long x, y, modulus_bytelen, derlen; int err; LTC_ARGCHK(msghash != NULL); LTC_ARGCHK(sig != NULL); LTC_ARGCHK(res != NULL); /* default to invalid */ *res = 0; /* valid hash ? */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } /* get derlen */ derlen = hash_descriptor[hash_idx].DERlen; /* get modulus len */ modulus_bytelen = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); /* valid sizes? */ if ((msghashlen + 3 + derlen > modulus_bytelen) || (siglen != modulus_bytelen)) { return CRYPT_PK_INVALID_SIZE; } /* packet is 0x00 0x01 PS 0x00 T, where PS == 0xFF repeated modulus_bytelen - 3 - derlen - msghashlen times, T == DER || hash */ x = 0; if (sig[x++] != 0x00 || sig[x++] != 0x01) { return CRYPT_OK; } /* now follows (modulus_bytelen - 3 - derlen - msghashlen) 0xFF bytes */ for (y = 0; y < (modulus_bytelen - 3 - derlen - msghashlen); y++) { if (sig[x++] != 0xFF) { return CRYPT_OK; } } if (sig[x++] != 0x00) { return CRYPT_OK; } for (y = 0; y < derlen; y++) { if (sig[x++] != hash_descriptor[hash_idx].DER[y]) { return CRYPT_OK; } } if (memcmp(msghash, sig+x, msghashlen) == 0) { *res = 1; } return CRYPT_OK; } #endif --- NEW FILE: pkcs_1_pss_decode.c --- /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tom...@gm..., http://libtomcrypt.org */ #include "tomcrypt.h" /** @file pkcs_1_pss_decode.c PKCS #1 PSS Signature Padding, Tom St Denis */ #ifdef PKCS_1 /** PKCS #1 v2.00 PSS decode @param msghash The hash to verify @param msghashlen The length of the hash (octets) @param sig The signature data (encoded data) @param siglen The length of the signature data (octets) @param saltlen The length of the salt used (octets) @param hash_idx The index of the hash desired @param modulus_bitlen The bit length of the RSA modulus @param res [out] The result of the comparison, 1==valid, 0==invalid @return CRYPT_OK if successful (even if the comparison failed) */ int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, const unsigned char *sig, unsigned long siglen, unsigned long saltlen, int hash_idx, unsigned long modulus_bitlen, int *res) { unsigned char *DB, *mask, *salt, *hash; unsigned long x, y, hLen, modulus_len; int err; hash_state md; LTC_ARGCHK(msghash != NULL); LTC_ARGCHK(res != NULL); /* default to invalid */ *res = 0; /* ensure hash is valid */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } hLen = hash_descriptor[hash_idx].hashsize; modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); /* check sizes */ if ((saltlen > modulus_len) || (modulus_len < hLen + saltlen + 2) || (siglen != modulus_len)) { return CRYPT_PK_INVALID_SIZE; } /* allocate ram for DB/mask/salt/hash of size modulus_len */ DB = XMALLOC(modulus_len); mask = XMALLOC(modulus_len); salt = XMALLOC(modulus_len); hash = XMALLOC(modulus_len); if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) { if (DB != NULL) { XFREE(DB); } if (mask != NULL) { XFREE(mask); } if (salt != NULL) { XFREE(salt); } if (hash != NULL) { XFREE(hash); } return CRYPT_MEM; } /* ensure the 0xBC byte */ if (sig[siglen-1] != 0xBC) { err = CRYPT_OK; goto LBL_ERR; } /* copy out the DB */ for (x = 0; x < modulus_len - hLen - 1; x++) { DB[x] = sig[x]; } /* copy out the hash */ for (y = 0; y < hLen; y++) { hash[y] = sig[x++]; } /* check the MSB */ if ((sig[0] & ~(0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)))) != 0) { err = CRYPT_OK; goto LBL_ERR; } /* generate mask of length modulus_len - hLen - 1 from hash */ if ((err = pkcs_1_mgf1(hash, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) { goto LBL_ERR; } /* xor against DB */ for (y = 0; y < (modulus_len - hLen - 1); y++) { DB[y] ^= mask[y]; } /* now clear the first byte [make sure smaller than modulus] */ DB[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)); /* DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */ /* check for zeroes and 0x01 */ for (x = 0; x < modulus_len - saltlen - hLen - 2; x++) { if (DB[x] != 0x00) { err = CRYPT_OK; goto LBL_ERR; } } /* check for the 0x01 */ if (DB[x++] != 0x01) { err = CRYPT_OK; goto LBL_ERR; } /* M = (eight) 0x00 || msghash || salt, mask = H(M) */ if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) { goto LBL_ERR; } zeromem(mask, 8); if ((err = hash_descriptor[hash_idx].process(&md, mask, 8)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx].process(&md, DB+x, saltlen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx].done(&md, mask)) != CRYPT_OK) { goto LBL_ERR; } /* mask == hash means valid signature */ if (memcmp(mask, hash, hLen) == 0) { *res = 1; } err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(DB, modulus_len); zeromem(mask, modulus_len); zeromem(salt, modulus_len); zeromem(hash, modulus_len); #endif XFREE(hash); XFREE(salt); XFREE(mask); XFREE(DB); return err; } #endif /* PKCS_1 */ --- NEW FILE: pkcs_1_oaep_encode.c --- /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tom...@gm..., http://libtomcrypt.org */ #include "tomcrypt.h" /** @file pkcs_1_oaep_encode.c OAEP Padding for PKCS #1, Tom St Denis */ #ifdef PKCS_1 /** PKCS #1 v2.00 OAEP encode @param msg The data to encode @param msglen The length of the data to encode (octets) @param lparam A session or system parameter (can be NULL) @param lparamlen The length of the lparam data @param modulus_bitlen The bit length of the RSA modulus @param prng An active PRNG state @param prng_idx The index of the PRNG desired @param hash_idx The index of the hash desired @param out [out] The destination for the encoded data @param outlen [in/out] The max size and resulting size of the encoded data @return CRYPT_OK if successful */ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, const unsigned char *lparam, unsigned long lparamlen, unsigned long modulus_bitlen, prng_state *prng, int prng_idx, int hash_idx, unsigned char *out, unsigned long *outlen) { unsigned char *DB, *seed, *mask; unsigned long hLen, x, y, modulus_len; int err; LTC_ARGCHK(msg != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* test valid hash */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } /* valid prng */ if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { return err; } hLen = hash_descriptor[hash_idx].hashsize; modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); /* test message size */ if ((2*hLen >= (modulus_len - 2)) || (msglen > (modulus_len - 2*hLen - 2))) { return CRYPT_PK_INVALID_SIZE; } /* allocate ram for DB/mask/salt of size modulus_len */ DB = XMALLOC(modulus_len); mask = XMALLOC(modulus_len); seed = XMALLOC(modulus_len); if (DB == NULL || mask == NULL || seed == NULL) { if (DB != NULL) { XFREE(DB); } if (mask != NULL) { XFREE(mask); } if (seed != NULL) { XFREE(seed); } return CRYPT_MEM; } /* get lhash */ /* DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */ x = modulus_len; if (lparam != NULL) { if ((err = hash_memory(hash_idx, lparam, lparamlen, DB, &x)) != CRYPT_OK) { goto LBL_ERR; } } else { /* can't pass hash_memory a NULL so use DB with zero length */ if ((err = hash_memory(hash_idx, DB, 0, DB, &x)) != CRYPT_OK) { goto LBL_ERR; } } /* append PS then 0x01 (to lhash) */ x = hLen; y = modulus_len - msglen - 2*hLen - 2; while (y--) { DB[x++] = 0x00; } DB[x++] = 0x01; /* message */ y = msglen; while (y--) { DB[x++] = *msg++; } /* now choose a random seed */ if (prng_descriptor[prng_idx].read(seed, hLen, prng) != hLen) { err = CRYPT_ERROR_READPRNG; goto LBL_ERR; } /* compute MGF1 of seed (k - hlen - 1) */ if ((err = pkcs_1_mgf1(seed, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) { goto LBL_ERR; } /* xor against DB */ for (y = 0; y < (modulus_len - hLen - 1); y++) { DB[y] ^= mask[y]; } /* compute MGF1 of maskedDB (hLen) */ if ((err = pkcs_1_mgf1(DB, modulus_len - hLen - 1, hash_idx, mask, hLen)) != CRYPT_OK) { goto LBL_ERR; } /* XOR against seed */ for (y = 0; y < hLen; y++) { seed[y] ^= mask[y]; } /* create string of length modulus_len */ if (*outlen < modulus_len) { err = CRYPT_BUFFER_OVERFLOW; goto LBL_ERR; } /* start output which is 0x00 || maskedSeed || maskedDB */ x = 0; out[x++] = 0x00; for (y = 0; y < hLen; y++) { out[x++] = seed[y]; } for (y = 0; y < modulus_len - hLen - 1; y++) { out[x++] = DB[y]; } *outlen = x; err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(DB, modulus_len); zeromem(seed, modulus_len); zeromem(mask, modulus_len); #endif XFREE(seed); XFREE(mask); XFREE(DB); return err; } #endif /* PKCS_1 */ --- NEW FILE: pkcs_1_v15_es_encode.c --- /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tom...@gm..., http://libtomcrypt.org */ #include "tomcrypt.h" /** @file pkcs_1_v15_es_encode.c v1.5 Encryption Padding for PKCS #1, Tom St Denis */ #ifdef PKCS_1 /** PKCS #1 v1.5 Encryption Padding @param msg The data to encode @param msglen The length of the data (octets) @param modulus_bitlen The bit length of the RSA modulus @param prng An active PRNG @param prng_idx The index of the PRNG desired @param out [out] The destination of the padding @param outlen [in/out] The max size and resulting size of the padding @return CRYPT_OK if successful */ int pkcs_1_v15_es_encode(const unsigned char *msg, unsigned long msglen, unsigned long modulus_bitlen, prng_state *prng, int prng_idx, unsigned char *out, unsigned long *outlen) { unsigned long modulus_bytelen, x, y; LTC_ARGCHK(msg != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* get modulus len */ modulus_bytelen = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); if (modulus_bytelen < 12) { return CRYPT_INVALID_ARG; } /* verify length */ if (msglen > (modulus_bytelen - 11) || *outlen < modulus_bytelen) { return CRYPT_PK_INVALID_SIZE; } /* 0x00 0x02 PS 0x00 M */ x = 0; out[x++] = 0x00; out[x++] = 0x02; y = modulus_bytelen - msglen - 3; if (prng_descriptor[prng_idx].read(out+x, y, prng) != y) { return CRYPT_ERROR_READPRNG; } x += y; out[x++] = 0x00; XMEMCPY(out+x, msg, msglen); *outlen = modulus_bytelen; return CRYPT_OK; } #endif /* PKCS_1 */ --- NEW FILE: pkcs_1_v15_sa_encode.c --- /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tom...@gm..., http://libtomcrypt.org */ #include "tomcrypt.h" /** @file pkcs_1_v15_sa_encode.c PKCS #1 v1.5 Signature Padding, Tom St Denis */ #ifdef PKCS_1 /** Perform PKCS #1 v1.5 Signature Padding @param msghash The hash you wish to incorporate in the padding @param msghashlen The length of the hash @param hash_idx The index of the hash used @param modulus_bitlen The length of the RSA modulus that will sign this (bits) @param out [out] Where to store the padded data @param outlen [in/out] Max size and resulting size of the padded data @return CRYPT_OK if successful */ int pkcs_1_v15_sa_encode(const unsigned char *msghash, unsigned long msghashlen, int hash_idx, unsigned long modulus_bitlen, unsigned char *out, unsigned long *outlen) { unsigned long derlen, modulus_bytelen, x, y; int err; LTC_ARGCHK(msghash != NULL) LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } /* hack, to detect any hash without a DER OID */ if (hash_descriptor[hash_idx].DERlen == 0) { return CRYPT_INVALID_ARG; } /* get modulus len */ modulus_bytelen = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); /* get der len ok? Forgive my lame German accent.... */ derlen = hash_descriptor[hash_idx].DERlen; /* valid sizes? */ if (msghashlen + 3 + derlen > modulus_bytelen) { return CRYPT_PK_INVALID_SIZE; } if (*outlen < modulus_bytelen) { return CRYPT_BUFFER_OVERFLOW; } /* packet is 0x00 0x01 PS 0x00 T, where PS == 0xFF repeated modulus_bytelen - 3 - derlen - msghashlen times, T == DER || hash */ x = 0; out[x++] = 0x00; out[x++] = 0x01; for (y = 0; y < (modulus_bytelen - 3 - derlen - msghashlen); y++) { out[x++] = 0xFF; } out[x++] = 0x00; for (y = 0; y < derlen; y++) { out[x++] = hash_descriptor[hash_idx].DER[y]; } for (y = 0; y < msghashlen; y++) { out[x++] = msghash[y]; } *outlen = modulus_bytelen; return CRYPT_OK; } #endif /* PKCS_1 */ |