summaryrefslogtreecommitdiff
path: root/libtomcrypt/src/pk/rsa
diff options
context:
space:
mode:
Diffstat (limited to 'libtomcrypt/src/pk/rsa')
-rw-r--r--libtomcrypt/src/pk/rsa/rsa_decrypt_key.c26
-rw-r--r--libtomcrypt/src/pk/rsa/rsa_encrypt_key.c28
-rw-r--r--libtomcrypt/src/pk/rsa/rsa_export.c70
-rw-r--r--libtomcrypt/src/pk/rsa/rsa_exptmod.c131
-rw-r--r--libtomcrypt/src/pk/rsa/rsa_free.c12
-rw-r--r--libtomcrypt/src/pk/rsa/rsa_get_size.c40
-rw-r--r--libtomcrypt/src/pk/rsa/rsa_import.c106
-rw-r--r--libtomcrypt/src/pk/rsa/rsa_import_pkcs8.c153
-rw-r--r--libtomcrypt/src/pk/rsa/rsa_import_x509.c118
-rw-r--r--libtomcrypt/src/pk/rsa/rsa_make_key.c39
-rw-r--r--libtomcrypt/src/pk/rsa/rsa_set.c134
-rw-r--r--libtomcrypt/src/pk/rsa/rsa_sign_hash.c98
-rw-r--r--libtomcrypt/src/pk/rsa/rsa_sign_saltlen_get.c47
-rw-r--r--libtomcrypt/src/pk/rsa/rsa_verify_hash.c114
14 files changed, 859 insertions, 257 deletions
diff --git a/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c b/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c
index 31d841f..9e1bced 100644
--- a/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c
+++ b/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c
@@ -5,20 +5,18 @@
*
* The library is free for all purposes without any express
* guarantee it works.
- *
- * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
*/
#include "tomcrypt.h"
/**
@file rsa_decrypt_key.c
- RSA LTC_PKCS #1 Decryption, Tom St Denis and Andreas Lange
+ RSA PKCS #1 Decryption, Tom St Denis and Andreas Lange
*/
#ifdef LTC_MRSA
/**
- LTC_PKCS #1 decrypt then v1.5 or OAEP depad
+ PKCS #1 decrypt then v1.5 or OAEP depad
@param in The ciphertext
@param inlen The length of the ciphertext (octets)
@param out [out] The plaintext
@@ -26,7 +24,7 @@
@param lparam The system "lparam" value
@param lparamlen The length of the lparam value (octets)
@param hash_idx The index of the hash desired
- @param padding Type of padding (LTC_LTC_PKCS_1_OAEP or LTC_LTC_PKCS_1_V1_5)
+ @param padding Type of padding (LTC_PKCS_1_OAEP or LTC_PKCS_1_V1_5)
@param stat [out] Result of the decryption, 1==valid, 0==invalid
@param key The corresponding private RSA key
@return CRYPT_OK if succcessul (even if invalid)
@@ -51,12 +49,12 @@ int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen,
/* valid padding? */
- if ((padding != LTC_LTC_PKCS_1_V1_5) &&
- (padding != LTC_LTC_PKCS_1_OAEP)) {
+ if ((padding != LTC_PKCS_1_V1_5) &&
+ (padding != LTC_PKCS_1_OAEP)) {
return CRYPT_PK_INVALID_PADDING;
}
- if (padding == LTC_LTC_PKCS_1_OAEP) {
+ if (padding == LTC_PKCS_1_OAEP) {
/* valid hash ? */
if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
return err;
@@ -85,13 +83,13 @@ int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen,
return err;
}
- if (padding == LTC_LTC_PKCS_1_OAEP) {
+ if (padding == LTC_PKCS_1_OAEP) {
/* now OAEP decode the packet */
err = pkcs_1_oaep_decode(tmp, x, lparam, lparamlen, modulus_bitlen, hash_idx,
out, outlen, stat);
} else {
- /* now LTC_PKCS #1 v1.5 depad the packet */
- err = pkcs_1_v1_5_decode(tmp, x, LTC_LTC_PKCS_1_EME, modulus_bitlen, out, outlen, stat);
+ /* now PKCS #1 v1.5 depad the packet */
+ err = pkcs_1_v1_5_decode(tmp, x, LTC_PKCS_1_EME, modulus_bitlen, out, outlen, stat);
}
XFREE(tmp);
@@ -100,6 +98,6 @@ int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen,
#endif /* LTC_MRSA */
-/* $Source$ */
-/* $Revision$ */
-/* $Date$ */
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c b/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c
index edb7e65..ef066d2 100644
--- a/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c
+++ b/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c
@@ -5,20 +5,18 @@
*
* The library is free for all purposes without any express
* guarantee it works.
- *
- * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
*/
#include "tomcrypt.h"
/**
@file rsa_encrypt_key.c
- RSA LTC_PKCS #1 encryption, Tom St Denis and Andreas Lange
+ RSA PKCS #1 encryption, Tom St Denis and Andreas Lange
*/
#ifdef LTC_MRSA
/**
- (LTC_PKCS #1 v2.0) OAEP pad then encrypt
+ (PKCS #1 v2.0) OAEP pad then encrypt
@param in The plaintext
@param inlen The length of the plaintext (octets)
@param out [out] The ciphertext
@@ -28,7 +26,7 @@
@param prng An active PRNG
@param prng_idx The index of the desired prng
@param hash_idx The index of the desired hash
- @param padding Type of padding (LTC_LTC_PKCS_1_OAEP or LTC_LTC_PKCS_1_V1_5)
+ @param padding Type of padding (LTC_PKCS_1_OAEP or LTC_PKCS_1_V1_5)
@param key The RSA key to encrypt to
@return CRYPT_OK if successful
*/
@@ -46,8 +44,8 @@ int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen,
LTC_ARGCHK(key != NULL);
/* valid padding? */
- if ((padding != LTC_LTC_PKCS_1_V1_5) &&
- (padding != LTC_LTC_PKCS_1_OAEP)) {
+ if ((padding != LTC_PKCS_1_V1_5) &&
+ (padding != LTC_PKCS_1_OAEP)) {
return CRYPT_PK_INVALID_PADDING;
}
@@ -56,7 +54,7 @@ int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen,
return err;
}
- if (padding == LTC_LTC_PKCS_1_OAEP) {
+ if (padding == LTC_PKCS_1_OAEP) {
/* valid hash? */
if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
return err;
@@ -73,7 +71,7 @@ int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen,
return CRYPT_BUFFER_OVERFLOW;
}
- if (padding == LTC_LTC_PKCS_1_OAEP) {
+ if (padding == LTC_PKCS_1_OAEP) {
/* OAEP pad the key */
x = *outlen;
if ((err = pkcs_1_oaep_encode(in, inlen, lparam,
@@ -82,21 +80,21 @@ int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen,
return err;
}
} else {
- /* LTC_PKCS #1 v1.5 pad the key */
+ /* PKCS #1 v1.5 pad the key */
x = *outlen;
- if ((err = pkcs_1_v1_5_encode(in, inlen, LTC_LTC_PKCS_1_EME,
+ if ((err = pkcs_1_v1_5_encode(in, inlen, LTC_PKCS_1_EME,
modulus_bitlen, prng, prng_idx,
out, &x)) != CRYPT_OK) {
return err;
}
}
- /* rsa exptmod the OAEP or LTC_PKCS #1 v1.5 pad */
+ /* rsa exptmod the OAEP or PKCS #1 v1.5 pad */
return ltc_mp.rsa_me(out, x, out, outlen, PK_PUBLIC, key);
}
#endif /* LTC_MRSA */
-/* $Source$ */
-/* $Revision$ */
-/* $Date$ */
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/libtomcrypt/src/pk/rsa/rsa_export.c b/libtomcrypt/src/pk/rsa/rsa_export.c
index 40cb066..a9885de 100644
--- a/libtomcrypt/src/pk/rsa/rsa_export.c
+++ b/libtomcrypt/src/pk/rsa/rsa_export.c
@@ -5,29 +5,28 @@
*
* The library is free for all purposes without any express
* guarantee it works.
- *
- * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
*/
#include "tomcrypt.h"
/**
@file rsa_export.c
- Export RSA LTC_PKCS keys, Tom St Denis
-*/
+ Export RSA PKCS keys, Tom St Denis
+*/
#ifdef LTC_MRSA
/**
- This will export either an RSAPublicKey or RSAPrivateKey [defined in LTC_PKCS #1 v2.1]
+ This will export either an RSAPublicKey or RSAPrivateKey [defined in PKCS #1 v2.1]
@param out [out] Destination of the packet
@param outlen [in/out] The max size and resulting size of the packet
@param type The type of exported key (PK_PRIVATE or PK_PUBLIC)
@param key The RSA key to export
@return CRYPT_OK if successful
-*/
+*/
int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key)
{
unsigned long zero=0;
+ int err;
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
LTC_ARGCHK(key != NULL);
@@ -39,31 +38,60 @@ int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key
if (type == PK_PRIVATE) {
/* private key */
- /* output is
+ /* output is
Version, n, e, d, p, q, d mod (p-1), d mod (q - 1), 1/q mod p
*/
- return der_encode_sequence_multi(out, outlen,
- LTC_ASN1_SHORT_INTEGER, 1UL, &zero,
- LTC_ASN1_INTEGER, 1UL, key->N,
+ return der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &zero,
+ LTC_ASN1_INTEGER, 1UL, key->N,
LTC_ASN1_INTEGER, 1UL, key->e,
- LTC_ASN1_INTEGER, 1UL, key->d,
- LTC_ASN1_INTEGER, 1UL, key->p,
- LTC_ASN1_INTEGER, 1UL, key->q,
+ LTC_ASN1_INTEGER, 1UL, key->d,
+ LTC_ASN1_INTEGER, 1UL, key->p,
+ LTC_ASN1_INTEGER, 1UL, key->q,
LTC_ASN1_INTEGER, 1UL, key->dP,
- LTC_ASN1_INTEGER, 1UL, key->dQ,
- LTC_ASN1_INTEGER, 1UL, key->qP,
+ LTC_ASN1_INTEGER, 1UL, key->dQ,
+ LTC_ASN1_INTEGER, 1UL, key->qP,
LTC_ASN1_EOL, 0UL, NULL);
} else {
/* public key */
- return der_encode_sequence_multi(out, outlen,
- LTC_ASN1_INTEGER, 1UL, key->N,
- LTC_ASN1_INTEGER, 1UL, key->e,
+ unsigned long tmplen, *ptmplen;
+ unsigned char* tmp = NULL;
+
+ if (type & PK_STD) {
+ tmplen = (mp_count_bits(key->N)/8)*2+8;
+ tmp = XMALLOC(tmplen);
+ ptmplen = &tmplen;
+ if (tmp == NULL) {
+ return CRYPT_MEM;
+ }
+ }
+ else {
+ tmp = out;
+ ptmplen = outlen;
+ }
+
+ err = der_encode_sequence_multi(tmp, ptmplen,
+ LTC_ASN1_INTEGER, 1UL, key->N,
+ LTC_ASN1_INTEGER, 1UL, key->e,
LTC_ASN1_EOL, 0UL, NULL);
+
+ if ((err != CRYPT_OK) || !(type & PK_STD)) {
+ goto finish;
+ }
+
+ err = der_encode_subject_public_key_info(out, outlen,
+ PKA_RSA, tmp, tmplen, LTC_ASN1_NULL, NULL, 0);
+
+finish:
+ if (tmp != out)
+ XFREE(tmp);
+ return err;
+
}
}
#endif /* LTC_MRSA */
-/* $Source$ */
-/* $Revision$ */
-/* $Date$ */
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/libtomcrypt/src/pk/rsa/rsa_exptmod.c b/libtomcrypt/src/pk/rsa/rsa_exptmod.c
index 101a766..37f62d1 100644
--- a/libtomcrypt/src/pk/rsa/rsa_exptmod.c
+++ b/libtomcrypt/src/pk/rsa/rsa_exptmod.c
@@ -5,41 +5,43 @@
*
* The library is free for all purposes without any express
* guarantee it works.
- *
- * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
*/
#include "tomcrypt.h"
/**
@file rsa_exptmod.c
- RSA LTC_PKCS exptmod, Tom St Denis
-*/
+ RSA PKCS exptmod, Tom St Denis
+ Added RSA blinding --nmav
+*/
#ifdef LTC_MRSA
-/**
- Compute an RSA modular exponentiation
+/**
+ Compute an RSA modular exponentiation
@param in The input data to send into RSA
@param inlen The length of the input (octets)
- @param out [out] The destination
+ @param out [out] The destination
@param outlen [in/out] The max size and resulting size of the output
@param which Which exponent to use, e.g. PK_PRIVATE or PK_PUBLIC
- @param key The RSA key to use
+ @param key The RSA key to use
@return CRYPT_OK if successful
-*/
+*/
int rsa_exptmod(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen, int which,
rsa_key *key)
{
- void *tmp, *tmpa, *tmpb;
+ void *tmp, *tmpa, *tmpb;
+ #ifdef LTC_RSA_BLINDING
+ void *rnd, *rndi /* inverse of rnd */;
+ #endif
unsigned long x;
- int err;
+ int err, has_crt_parameters;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
LTC_ARGCHK(key != NULL);
-
+
/* is the key of the right type for the operation? */
if (which == PK_PRIVATE && (key->type != PK_PRIVATE)) {
return CRYPT_PK_NOT_PRIVATE;
@@ -51,8 +53,15 @@ int rsa_exptmod(const unsigned char *in, unsigned long inlen,
}
/* init and copy into tmp */
- if ((err = mp_init_multi(&tmp, &tmpa, &tmpb, NULL)) != CRYPT_OK) { return err; }
- if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, (int)inlen)) != CRYPT_OK) { goto error; }
+ if ((err = mp_init_multi(&tmp, &tmpa, &tmpb,
+#ifdef LTC_RSA_BLINDING
+ &rnd, &rndi,
+#endif /* LTC_RSA_BLINDING */
+ NULL)) != CRYPT_OK)
+ { return err; }
+ if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, (int)inlen)) != CRYPT_OK)
+ { goto error; }
+
/* sanity check on the input */
if (mp_cmp(key->N, tmp) == LTC_MP_LT) {
@@ -62,19 +71,75 @@ int rsa_exptmod(const unsigned char *in, unsigned long inlen,
/* are we using the private exponent and is the key optimized? */
if (which == PK_PRIVATE) {
- /* tmpa = tmp^dP mod p */
- if ((err = mp_exptmod(tmp, key->dP, key->p, tmpa)) != CRYPT_OK) { goto error; }
-
- /* tmpb = tmp^dQ mod q */
- if ((err = mp_exptmod(tmp, key->dQ, key->q, tmpb)) != CRYPT_OK) { goto error; }
-
- /* tmp = (tmpa - tmpb) * qInv (mod p) */
- if ((err = mp_sub(tmpa, tmpb, tmp)) != CRYPT_OK) { goto error; }
- if ((err = mp_mulmod(tmp, key->qP, key->p, tmp)) != CRYPT_OK) { goto error; }
-
- /* tmp = tmpb + q * tmp */
- if ((err = mp_mul(tmp, key->q, tmp)) != CRYPT_OK) { goto error; }
- if ((err = mp_add(tmp, tmpb, tmp)) != CRYPT_OK) { goto error; }
+ #ifdef LTC_RSA_BLINDING
+ /* do blinding */
+ err = mp_rand(rnd, mp_get_digit_count(key->N));
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+
+ /* rndi = 1/rnd mod N */
+ err = mp_invmod(rnd, key->N, rndi);
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+
+ /* rnd = rnd^e */
+ err = mp_exptmod( rnd, key->e, key->N, rnd);
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+
+ /* tmp = tmp*rnd mod N */
+ err = mp_mulmod( tmp, rnd, key->N, tmp);
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+ #endif /* LTC_RSA_BLINDING */
+
+ has_crt_parameters = (key->p != NULL) && (mp_get_digit_count(key->p) != 0) &&
+ (key->q != NULL) && (mp_get_digit_count(key->q) != 0) &&
+ (key->dP != NULL) && (mp_get_digit_count(key->dP) != 0) &&
+ (key->dQ != NULL) && (mp_get_digit_count(key->dQ) != 0) &&
+ (key->qP != NULL) && (mp_get_digit_count(key->qP) != 0);
+
+ if (!has_crt_parameters) {
+ /*
+ * In case CRT optimization parameters are not provided,
+ * the private key is directly used to exptmod it
+ */
+ if ((err = mp_exptmod(tmp, key->d, key->N, tmp)) != CRYPT_OK) { goto error; }
+ } else {
+ /* tmpa = tmp^dP mod p */
+ if ((err = mp_exptmod(tmp, key->dP, key->p, tmpa)) != CRYPT_OK) { goto error; }
+
+ /* tmpb = tmp^dQ mod q */
+ if ((err = mp_exptmod(tmp, key->dQ, key->q, tmpb)) != CRYPT_OK) { goto error; }
+
+ /* tmp = (tmpa - tmpb) * qInv (mod p) */
+ if ((err = mp_sub(tmpa, tmpb, tmp)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(tmp, key->qP, key->p, tmp)) != CRYPT_OK) { goto error; }
+
+ /* tmp = tmpb + q * tmp */
+ if ((err = mp_mul(tmp, key->q, tmp)) != CRYPT_OK) { goto error; }
+ if ((err = mp_add(tmp, tmpb, tmp)) != CRYPT_OK) { goto error; }
+ }
+
+ #ifdef LTC_RSA_BLINDING
+ /* unblind */
+ err = mp_mulmod( tmp, rndi, key->N, tmp);
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+ #endif
+
+ #ifdef LTC_RSA_CRT_HARDENING
+ if (has_crt_parameters) {
+ if ((err = mp_exptmod(tmp, key->e, key->N, tmpa)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_unsigned_bin(tmpb, (unsigned char *)in, (int)inlen)) != CRYPT_OK) { goto error; }
+ if (mp_cmp(tmpa, tmpb) != LTC_MP_EQ) { err = CRYPT_ERROR; goto error; }
+ }
+ #endif
} else {
/* exptmod it */
if ((err = mp_exptmod(tmp, key->e, key->N, tmp)) != CRYPT_OK) { goto error; }
@@ -102,12 +167,16 @@ int rsa_exptmod(const unsigned char *in, unsigned long inlen,
/* clean up and return */
err = CRYPT_OK;
error:
- mp_clear_multi(tmp, tmpa, tmpb, NULL);
+ mp_clear_multi(
+#ifdef LTC_RSA_BLINDING
+ rndi, rnd,
+#endif /* LTC_RSA_BLINDING */
+ tmpb, tmpa, tmp, NULL);
return err;
}
#endif
-/* $Source$ */
-/* $Revision$ */
-/* $Date$ */
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/libtomcrypt/src/pk/rsa/rsa_free.c b/libtomcrypt/src/pk/rsa/rsa_free.c
index bb6daef..1e62f09 100644
--- a/libtomcrypt/src/pk/rsa/rsa_free.c
+++ b/libtomcrypt/src/pk/rsa/rsa_free.c
@@ -5,15 +5,13 @@
*
* The library is free for all purposes without any express
* guarantee it works.
- *
- * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
*/
#include "tomcrypt.h"
/**
@file rsa_free.c
Free an RSA key, Tom St Denis
-*/
+*/
#ifdef LTC_MRSA
@@ -24,11 +22,11 @@
void rsa_free(rsa_key *key)
{
LTC_ARGCHKVD(key != NULL);
- mp_clear_multi(key->e, key->d, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL);
+ mp_cleanup_multi(&key->q, &key->p, &key->qP, &key->dP, &key->dQ, &key->N, &key->d, &key->e, NULL);
}
#endif
-/* $Source$ */
-/* $Revision$ */
-/* $Date$ */
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/libtomcrypt/src/pk/rsa/rsa_get_size.c b/libtomcrypt/src/pk/rsa/rsa_get_size.c
new file mode 100644
index 0000000..8c90194
--- /dev/null
+++ b/libtomcrypt/src/pk/rsa/rsa_get_size.c
@@ -0,0 +1,40 @@
+/* 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.
+ */
+#include "tomcrypt.h"
+
+/**
+ @file rsa_get_size.c
+ Retrieve the size of an RSA key, Steffen Jaeckel.
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ Retrieve the size in bytes of an RSA key.
+ @param key The RSA key
+ @return The size in bytes of the RSA key or INT_MAX on error.
+*/
+int rsa_get_size(rsa_key *key)
+{
+ int ret = INT_MAX;
+ LTC_ARGCHK(key != NULL);
+
+ if (key)
+ {
+ ret = mp_unsigned_bin_size(key->N);
+ } /* if */
+
+ return ret;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/libtomcrypt/src/pk/rsa/rsa_import.c b/libtomcrypt/src/pk/rsa/rsa_import.c
index 85c676b..84cd6f6 100644
--- a/libtomcrypt/src/pk/rsa/rsa_import.c
+++ b/libtomcrypt/src/pk/rsa/rsa_import.c
@@ -5,20 +5,18 @@
*
* The library is free for all purposes without any express
* guarantee it works.
- *
- * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
*/
#include "tomcrypt.h"
/**
@file rsa_import.c
- Import a LTC_PKCS RSA key, Tom St Denis
-*/
+ Import a PKCS RSA key, Tom St Denis
+*/
#ifdef LTC_MRSA
/**
- Import an RSAPublicKey or RSAPrivateKey [two-prime only, only support >= 1024-bit keys, defined in LTC_PKCS #1 v2.1]
+ Import an RSAPublicKey or RSAPrivateKey [two-prime only, only support >= 1024-bit keys, defined in PKCS #1 v2.1]
@param in The packet to import from
@param inlen It's length (octets)
@param key [out] Destination for newly imported key
@@ -28,87 +26,68 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
{
int err;
void *zero;
- unsigned char *tmpbuf;
- unsigned long t, x, y, z, tmpoid[16];
- ltc_asn1_list ssl_pubkey_hashoid[2];
- ltc_asn1_list ssl_pubkey[2];
+ unsigned char *tmpbuf=NULL;
+ unsigned long tmpbuf_len;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(ltc_mp.name != NULL);
/* init key */
- if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ,
+ if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ,
&key->dP, &key->qP, &key->p, &key->q, NULL)) != CRYPT_OK) {
return err;
}
/* see if the OpenSSL DER format RSA public key will work */
- tmpbuf = XCALLOC(1, MAX_RSA_SIZE*8);
+ tmpbuf_len = inlen;
+ tmpbuf = XCALLOC(1, tmpbuf_len);
if (tmpbuf == NULL) {
err = CRYPT_MEM;
goto LBL_ERR;
}
- /* this includes the internal hash ID and optional params (NULL in this case) */
- LTC_SET_ASN1(ssl_pubkey_hashoid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid)/sizeof(tmpoid[0]));
- LTC_SET_ASN1(ssl_pubkey_hashoid, 1, LTC_ASN1_NULL, NULL, 0);
-
- /* the actual format of the SSL DER key is odd, it stores a RSAPublicKey in a **BIT** string ... so we have to extract it
- then proceed to convert bit to octet
- */
- LTC_SET_ASN1(ssl_pubkey, 0, LTC_ASN1_SEQUENCE, &ssl_pubkey_hashoid, 2);
- LTC_SET_ASN1(ssl_pubkey, 1, LTC_ASN1_BIT_STRING, tmpbuf, MAX_RSA_SIZE*8);
-
- if (der_decode_sequence(in, inlen,
- ssl_pubkey, 2UL) == CRYPT_OK) {
-
- /* ok now we have to reassemble the BIT STRING to an OCTET STRING. Thanks OpenSSL... */
- for (t = y = z = x = 0; x < ssl_pubkey[1].size; x++) {
- y = (y << 1) | tmpbuf[x];
- if (++z == 8) {
- tmpbuf[t++] = (unsigned char)y;
- y = 0;
- z = 0;
- }
- }
+ err = der_decode_subject_public_key_info(in, inlen,
+ PKA_RSA, tmpbuf, &tmpbuf_len,
+ LTC_ASN1_NULL, NULL, 0);
+
+ if (err == CRYPT_OK) { /* SubjectPublicKeyInfo format */
/* now it should be SEQUENCE { INTEGER, INTEGER } */
- if ((err = der_decode_sequence_multi(tmpbuf, t,
- LTC_ASN1_INTEGER, 1UL, key->N,
- LTC_ASN1_INTEGER, 1UL, key->e,
+ if ((err = der_decode_sequence_multi(tmpbuf, tmpbuf_len,
+ LTC_ASN1_INTEGER, 1UL, key->N,
+ LTC_ASN1_INTEGER, 1UL, key->e,
LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
- XFREE(tmpbuf);
goto LBL_ERR;
}
- XFREE(tmpbuf);
key->type = PK_PUBLIC;
- return CRYPT_OK;
+ err = CRYPT_OK;
+ goto LBL_FREE;
}
- XFREE(tmpbuf);
- /* not SSL public key, try to match against LTC_PKCS #1 standards */
- if ((err = der_decode_sequence_multi(in, inlen,
- LTC_ASN1_INTEGER, 1UL, key->N,
- LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ /* not SSL public key, try to match against PKCS #1 standards */
+ err = der_decode_sequence_multi(in, inlen, LTC_ASN1_INTEGER, 1UL, key->N,
+ LTC_ASN1_EOL, 0UL, NULL);
+
+ if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) {
goto LBL_ERR;
}
if (mp_cmp_d(key->N, 0) == LTC_MP_EQ) {
- if ((err = mp_init(&zero)) != CRYPT_OK) {
+ if ((err = mp_init(&zero)) != CRYPT_OK) {
goto LBL_ERR;
}
/* it's a private key */
- if ((err = der_decode_sequence_multi(in, inlen,
- LTC_ASN1_INTEGER, 1UL, zero,
- LTC_ASN1_INTEGER, 1UL, key->N,
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_INTEGER, 1UL, zero,
+ LTC_ASN1_INTEGER, 1UL, key->N,
LTC_ASN1_INTEGER, 1UL, key->e,
- LTC_ASN1_INTEGER, 1UL, key->d,
- LTC_ASN1_INTEGER, 1UL, key->p,
- LTC_ASN1_INTEGER, 1UL, key->q,
+ LTC_ASN1_INTEGER, 1UL, key->d,
+ LTC_ASN1_INTEGER, 1UL, key->p,
+ LTC_ASN1_INTEGER, 1UL, key->q,
LTC_ASN1_INTEGER, 1UL, key->dP,
- LTC_ASN1_INTEGER, 1UL, key->dQ,
- LTC_ASN1_INTEGER, 1UL, key->qP,
+ LTC_ASN1_INTEGER, 1UL, key->dQ,
+ LTC_ASN1_INTEGER, 1UL, key->qP,
LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
mp_clear(zero);
goto LBL_ERR;
@@ -121,23 +100,30 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
goto LBL_ERR;
} else {
/* it's a public key and we lack e */
- if ((err = der_decode_sequence_multi(in, inlen,
- LTC_ASN1_INTEGER, 1UL, key->N,
- LTC_ASN1_INTEGER, 1UL, key->e,
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_INTEGER, 1UL, key->N,
+ LTC_ASN1_INTEGER, 1UL, key->e,
LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
goto LBL_ERR;
}
key->type = PK_PUBLIC;
}
- return CRYPT_OK;
+ err = CRYPT_OK;
+ goto LBL_FREE;
+
LBL_ERR:
mp_clear_multi(key->d, key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL);
+
+LBL_FREE:
+ if (tmpbuf != NULL)
+ XFREE(tmpbuf);
+
return err;
}
#endif /* LTC_MRSA */
-/* $Source$ */
-/* $Revision$ */
-/* $Date$ */
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/libtomcrypt/src/pk/rsa/rsa_import_pkcs8.c b/libtomcrypt/src/pk/rsa/rsa_import_pkcs8.c
new file mode 100644
index 0000000..8e15e06
--- /dev/null
+++ b/libtomcrypt/src/pk/rsa/rsa_import_pkcs8.c
@@ -0,0 +1,153 @@
+/* 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.
+ */
+#include "tomcrypt.h"
+
+/**
+ @file rsa_import_pkcs8.c
+ Import a PKCS RSA key
+*/
+
+#ifdef LTC_MRSA
+
+/* Public-Key Cryptography Standards (PKCS) #8:
+ * Private-Key Information Syntax Specification Version 1.2
+ * https://tools.ietf.org/html/rfc5208
+ *
+ * PrivateKeyInfo ::= SEQUENCE {
+ * version Version,
+ * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
+ * privateKey PrivateKey,
+ * attributes [0] IMPLICIT Attributes OPTIONAL }
+ * where:
+ * - Version ::= INTEGER
+ * - PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
+ * - PrivateKey ::= OCTET STRING
+ * - Attributes ::= SET OF Attribute
+ *
+ * EncryptedPrivateKeyInfo ::= SEQUENCE {
+ * encryptionAlgorithm EncryptionAlgorithmIdentifier,
+ * encryptedData EncryptedData }
+ * where:
+ * - EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+ * - EncryptedData ::= OCTET STRING
+ */
+
+/**
+ Import an RSAPublicKey or RSAPrivateKey in PKCS#8 format
+ @param in The packet to import from
+ @param inlen It's length (octets)
+ @param passwd The password for decrypting privkey (NOT SUPPORTED YET)
+ @param passwdlen Password's length (octets)
+ @param key [out] Destination for newly imported key
+ @return CRYPT_OK if successful, upon error allocated memory is freed
+*/
+int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen,
+ const void *passwd, unsigned long passwdlen,
+ rsa_key *key)
+{
+ int err;
+ void *zero, *iter;
+ unsigned char *buf1 = NULL, *buf2 = NULL;
+ unsigned long buf1len, buf2len;
+ unsigned long oid[16];
+ oid_st rsaoid;
+ ltc_asn1_list alg_seq[2], top_seq[3];
+ ltc_asn1_list alg_seq_e[2], key_seq_e[2], top_seq_e[2];
+ unsigned char *decrypted = NULL;
+ unsigned long decryptedlen;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ /* get RSA alg oid */
+ err = pk_get_oid(PKA_RSA, &rsaoid);
+ if (err != CRYPT_OK) { goto LBL_NOFREE; }
+
+ /* alloc buffers */
+ buf1len = inlen; /* approx. */
+ buf1 = XMALLOC(buf1len);
+ if (buf1 == NULL) { err = CRYPT_MEM; goto LBL_NOFREE; }
+ buf2len = inlen; /* approx. */
+ buf2 = XMALLOC(buf2len);
+ if (buf2 == NULL) { err = CRYPT_MEM; goto LBL_FREE1; }
+
+ /* init key */
+ err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, &zero, &iter, NULL);
+ if (err != CRYPT_OK) { goto LBL_FREE2; }
+
+ /* try to decode encrypted priv key */
+ LTC_SET_ASN1(key_seq_e, 0, LTC_ASN1_OCTET_STRING, buf1, buf1len);
+ LTC_SET_ASN1(key_seq_e, 1, LTC_ASN1_INTEGER, iter, 1UL);
+ LTC_SET_ASN1(alg_seq_e, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, 16UL);
+ LTC_SET_ASN1(alg_seq_e, 1, LTC_ASN1_SEQUENCE, key_seq_e, 2UL);
+ LTC_SET_ASN1(top_seq_e, 0, LTC_ASN1_SEQUENCE, alg_seq_e, 2UL);
+ LTC_SET_ASN1(top_seq_e, 1, LTC_ASN1_OCTET_STRING, buf2, buf2len);
+ err=der_decode_sequence(in, inlen, top_seq_e, 2UL);
+ if (err == CRYPT_OK) {
+ LTC_UNUSED_PARAM(passwd);
+ LTC_UNUSED_PARAM(passwdlen);
+ /* XXX: TODO encrypted pkcs8 not implemented yet */
+ /* fprintf(stderr, "decrypt: iter=%ld salt.len=%ld encdata.len=%ld\n", mp_get_int(iter), key_seq_e[0].size, top_seq_e[1].size); */
+ err = CRYPT_PK_INVALID_TYPE;
+ goto LBL_ERR;
+ }
+ else {
+ decrypted = (unsigned char *)in;
+ decryptedlen = inlen;
+ }
+
+ /* try to decode unencrypted priv key */
+ LTC_SET_ASN1(alg_seq, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, 16UL);
+ LTC_SET_ASN1(alg_seq, 1, LTC_ASN1_NULL, NULL, 0UL);
+ LTC_SET_ASN1(top_seq, 0, LTC_ASN1_INTEGER, zero, 1UL);
+ LTC_SET_ASN1(top_seq, 1, LTC_ASN1_SEQUENCE, alg_seq, 2UL);
+ LTC_SET_ASN1(top_seq, 2, LTC_ASN1_OCTET_STRING, buf1, buf1len);
+ err=der_decode_sequence(decrypted, decryptedlen, top_seq, 3UL);
+ if (err != CRYPT_OK) { goto LBL_ERR; }
+
+ /* check alg oid */
+ if ((alg_seq[0].size != rsaoid.OIDlen) ||
+ XMEMCMP(rsaoid.OID, alg_seq[0].data, rsaoid.OIDlen * sizeof(rsaoid.OID[0]))) {
+ err = CRYPT_PK_INVALID_TYPE;
+ goto LBL_ERR;
+ }
+
+ err = der_decode_sequence_multi(buf1, top_seq[2].size,
+ LTC_ASN1_INTEGER, 1UL, zero,
+ LTC_ASN1_INTEGER, 1UL, key->N,
+ LTC_ASN1_INTEGER, 1UL, key->e,
+ LTC_ASN1_INTEGER, 1UL, key->d,
+ LTC_ASN1_INTEGER, 1UL, key->p,
+ LTC_ASN1_INTEGER, 1UL, key->q,
+ LTC_ASN1_INTEGER, 1UL, key->dP,
+ LTC_ASN1_INTEGER, 1UL, key->dQ,
+ LTC_ASN1_INTEGER, 1UL, key->qP,
+ LTC_ASN1_EOL, 0UL, NULL);
+ if (err != CRYPT_OK) { goto LBL_ERR; }
+ key->type = PK_PRIVATE;
+ err = CRYPT_OK;
+ goto LBL_FREE2;
+
+LBL_ERR:
+ rsa_free(key);
+LBL_FREE2:
+ mp_clear_multi(iter, zero, NULL);
+ XFREE(buf2);
+LBL_FREE1:
+ XFREE(buf1);
+LBL_NOFREE:
+ return err;
+}
+
+#endif /* LTC_MRSA */
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/libtomcrypt/src/pk/rsa/rsa_import_x509.c b/libtomcrypt/src/pk/rsa/rsa_import_x509.c
new file mode 100644
index 0000000..0f2d5f1
--- /dev/null
+++ b/libtomcrypt/src/pk/rsa/rsa_import_x509.c
@@ -0,0 +1,118 @@
+/* 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.
+ */
+#include "tomcrypt.h"
+
+/**
+ @file rsa_import.c
+ Import an RSA key from a X.509 certificate, Steffen Jaeckel
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ Import an RSA key from a X.509 certificate
+ @param in The packet to import from
+ @param inlen It's length (octets)
+ @param key [out] Destination for newly imported key
+ @return CRYPT_OK if successful, upon error allocated memory is freed
+*/
+int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key)
+{
+ int err;
+ unsigned char *tmpbuf;
+ unsigned long tmpbuf_len, tmp_inlen;
+ ltc_asn1_list *decoded_list = NULL, *l;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ /* init key */
+ if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ,
+ &key->dP, &key->qP, &key->p, &key->q, NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ tmpbuf_len = inlen;
+ tmpbuf = XCALLOC(1, tmpbuf_len);
+ if (tmpbuf == NULL) {
+ err = CRYPT_MEM;
+ goto LBL_ERR;
+ }
+
+ tmp_inlen = inlen;
+ if ((err = der_decode_sequence_flexi(in, &tmp_inlen, &decoded_list)) == CRYPT_OK) {
+ l = decoded_list;
+ /* Move 2 levels up in the tree
+ SEQUENCE
+ SEQUENCE
+ ...
+ */
+ if (l->type == LTC_ASN1_SEQUENCE && l->child) {
+ l = l->child;
+ if (l->type == LTC_ASN1_SEQUENCE && l->child) {
+ l = l->child;
+
+ err = CRYPT_ERROR;
+
+ /* Move forward in the tree until we find this combination
+ ...
+ SEQUENCE
+ SEQUENCE
+ OBJECT IDENTIFIER 1.2.840.113549.1.1.1
+ NULL
+ BIT STRING
+ */
+ do {
+ /* The additional check for l->data is there to make sure
+ * we won't try to decode a list that has been 'shrunk'
+ */
+ if (l->type == LTC_ASN1_SEQUENCE && l->data && l->child &&
+ l->child->type == LTC_ASN1_SEQUENCE && l->child->child &&
+ l->child->child->type == LTC_ASN1_OBJECT_IDENTIFIER && l->child->next &&
+ l->child->next->type == LTC_ASN1_BIT_STRING) {
+ err = der_decode_subject_public_key_info(l->data, l->size,
+ PKA_RSA, tmpbuf, &tmpbuf_len,
+ LTC_ASN1_NULL, NULL, 0);
+ if (err == CRYPT_OK) {
+ /* now it should be SEQUENCE { INTEGER, INTEGER } */
+ if ((err = der_decode_sequence_multi(tmpbuf, tmpbuf_len,
+ LTC_ASN1_INTEGER, 1UL, key->N,
+ LTC_ASN1_INTEGER, 1UL, key->e,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ key->type = PK_PUBLIC;
+ err = CRYPT_OK;
+ goto LBL_FREE;
+ }
+ }
+ l = l->next;
+ } while(l);
+ }
+ }
+ }
+
+
+LBL_ERR:
+ rsa_free(key);
+
+LBL_FREE:
+ if (decoded_list) der_free_sequence_flexi(decoded_list);
+ if (tmpbuf != NULL) XFREE(tmpbuf);
+
+ return err;
+}
+
+#endif /* LTC_MRSA */
+
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/libtomcrypt/src/pk/rsa/rsa_make_key.c b/libtomcrypt/src/pk/rsa/rsa_make_key.c
index d62e37e..c5c4c28 100644
--- a/libtomcrypt/src/pk/rsa/rsa_make_key.c
+++ b/libtomcrypt/src/pk/rsa/rsa_make_key.c
@@ -5,19 +5,17 @@
*
* The library is free for all purposes without any express
* guarantee it works.
- *
- * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
*/
#include "tomcrypt.h"
/**
@file rsa_make_key.c
RSA key generation, Tom St Denis
-*/
+*/
#ifdef LTC_MRSA
-/**
+/**
Create an RSA key
@param prng An active PRNG state
@param wprng The index of the PRNG desired
@@ -33,10 +31,7 @@ int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key)
LTC_ARGCHK(ltc_mp.name != NULL);
LTC_ARGCHK(key != NULL);
-
- if ((size < (MIN_RSA_SIZE/8)) || (size > (MAX_RSA_SIZE/8))) {
- return CRYPT_INVALID_KEYSIZE;
- }
+ LTC_ARGCHK(size > 0);
if ((e < 3) || ((e & 1) == 0)) {
return CRYPT_INVALID_ARG;
@@ -51,26 +46,26 @@ int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key)
}
/* make primes p and q (optimization provided by Wayne Scott) */
- if ((err = mp_set_int(tmp3, e)) != CRYPT_OK) { goto errkey; } /* tmp3 = e */
+ if ((err = mp_set_int(tmp3, e)) != CRYPT_OK) { goto cleanup; } /* tmp3 = e */
/* make prime "p" */
do {
- if ((err = rand_prime( p, size/2, prng, wprng)) != CRYPT_OK) { goto errkey; }
- if ((err = mp_sub_d( p, 1, tmp1)) != CRYPT_OK) { goto errkey; } /* tmp1 = p-1 */
- if ((err = mp_gcd( tmp1, tmp3, tmp2)) != CRYPT_OK) { goto errkey; } /* tmp2 = gcd(p-1, e) */
+ if ((err = rand_prime( p, size/2, prng, wprng)) != CRYPT_OK) { goto cleanup; }
+ if ((err = mp_sub_d( p, 1, tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = p-1 */
+ if ((err = mp_gcd( tmp1, tmp3, tmp2)) != CRYPT_OK) { goto cleanup; } /* tmp2 = gcd(p-1, e) */
} while (mp_cmp_d( tmp2, 1) != 0); /* while e divides p-1 */
/* make prime "q" */
do {
- if ((err = rand_prime( q, size/2, prng, wprng)) != CRYPT_OK) { goto errkey; }
- if ((err = mp_sub_d( q, 1, tmp1)) != CRYPT_OK) { goto errkey; } /* tmp1 = q-1 */
- if ((err = mp_gcd( tmp1, tmp3, tmp2)) != CRYPT_OK) { goto errkey; } /* tmp2 = gcd(q-1, e) */
+ if ((err = rand_prime( q, size/2, prng, wprng)) != CRYPT_OK) { goto cleanup; }
+ if ((err = mp_sub_d( q, 1, tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = q-1 */
+ if ((err = mp_gcd( tmp1, tmp3, tmp2)) != CRYPT_OK) { goto cleanup; } /* tmp2 = gcd(q-1, e) */
} while (mp_cmp_d( tmp2, 1) != 0); /* while e divides q-1 */
/* tmp1 = lcm(p-1, q-1) */
- if ((err = mp_sub_d( p, 1, tmp2)) != CRYPT_OK) { goto errkey; } /* tmp2 = p-1 */
+ if ((err = mp_sub_d( p, 1, tmp2)) != CRYPT_OK) { goto cleanup; } /* tmp2 = p-1 */
/* tmp1 = q-1 (previous do/while loop) */
- if ((err = mp_lcm( tmp1, tmp2, tmp1)) != CRYPT_OK) { goto errkey; } /* tmp1 = lcm(p-1, q-1) */
+ if ((err = mp_lcm( tmp1, tmp2, tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = lcm(p-1, q-1) */
/* make key */
if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL)) != CRYPT_OK) {
@@ -99,14 +94,14 @@ int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key)
err = CRYPT_OK;
goto cleanup;
errkey:
- mp_clear_multi(key->d, key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL);
+ rsa_free(key);
cleanup:
- mp_clear_multi(tmp3, tmp2, tmp1, p, q, NULL);
+ mp_clear_multi(tmp3, tmp2, tmp1, q, p, NULL);
return err;
}
#endif
-/* $Source$ */
-/* $Revision$ */
-/* $Date$ */
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/libtomcrypt/src/pk/rsa/rsa_set.c b/libtomcrypt/src/pk/rsa/rsa_set.c
new file mode 100644
index 0000000..0d540c4
--- /dev/null
+++ b/libtomcrypt/src/pk/rsa/rsa_set.c
@@ -0,0 +1,134 @@
+/* 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.
+ */
+#include "tomcrypt.h"
+
+
+#ifdef LTC_MRSA
+
+/**
+ Import RSA key from raw numbers
+
+ @param N RSA's N
+ @param Nlen RSA's N's length
+ @param e RSA's e
+ @param elen RSA's e's length
+ @param d RSA's d (only private key, NULL for public key)
+ @param dlen RSA's d's length
+ @param key [out] the destination for the imported key
+ @return CRYPT_OK if successful
+*/
+int rsa_set_key(const unsigned char *N, unsigned long Nlen,
+ const unsigned char *e, unsigned long elen,
+ const unsigned char *d, unsigned long dlen,
+ rsa_key *key)
+{
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(N != NULL);
+ LTC_ARGCHK(e != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL);
+ if (err != CRYPT_OK) return err;
+
+ if ((err = mp_read_unsigned_bin(key->N , (unsigned char *)N , Nlen)) != CRYPT_OK) { goto LBL_ERR; }
+ if ((err = mp_read_unsigned_bin(key->e , (unsigned char *)e , elen)) != CRYPT_OK) { goto LBL_ERR; }
+ if (d && dlen) {
+ if ((err = mp_read_unsigned_bin(key->d , (unsigned char *)d , dlen)) != CRYPT_OK) { goto LBL_ERR; }
+ key->type = PK_PRIVATE;
+ }
+ else {
+ key->type = PK_PUBLIC;
+ }
+ return CRYPT_OK;
+
+LBL_ERR:
+ rsa_free(key);
+ return err;
+}
+
+/**
+ Import factors of an RSA key from raw numbers
+
+ Only for private keys.
+
+ @param p RSA's p
+ @param plen RSA's p's length
+ @param q RSA's q
+ @param qlen RSA's q's length
+ @param key [out] the destination for the imported key
+ @return CRYPT_OK if successful
+*/
+int rsa_set_factors(const unsigned char *p, unsigned long plen,
+ const unsigned char *q, unsigned long qlen,
+ rsa_key *key)
+{
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(p != NULL);
+ LTC_ARGCHK(q != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ if (key->type != PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH;
+
+ if ((err = mp_read_unsigned_bin(key->p , (unsigned char *)p , plen)) != CRYPT_OK) { goto LBL_ERR; }
+ if ((err = mp_read_unsigned_bin(key->q , (unsigned char *)q , qlen)) != CRYPT_OK) { goto LBL_ERR; }
+ return CRYPT_OK;
+
+LBL_ERR:
+ rsa_free(key);
+ return err;
+}
+
+/**
+ Import CRT parameters of an RSA key from raw numbers
+
+ Only for private keys.
+
+ @param dP RSA's dP
+ @param dPlen RSA's dP's length
+ @param dQ RSA's dQ
+ @param dQlen RSA's dQ's length
+ @param qP RSA's qP
+ @param qPlen RSA's qP's length
+ @param key [out] the destination for the imported key
+ @return CRYPT_OK if successful
+*/
+int rsa_set_crt_params(const unsigned char *dP, unsigned long dPlen,
+ const unsigned char *dQ, unsigned long dQlen,
+ const unsigned char *qP, unsigned long qPlen,
+ rsa_key *key)
+{
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(dP != NULL);
+ LTC_ARGCHK(dQ != NULL);
+ LTC_ARGCHK(qP != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ if (key->type != PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH;
+
+ if ((err = mp_read_unsigned_bin(key->dP, (unsigned char *)dP, dPlen)) != CRYPT_OK) { goto LBL_ERR; }
+ if ((err = mp_read_unsigned_bin(key->dQ, (unsigned char *)dQ, dQlen)) != CRYPT_OK) { goto LBL_ERR; }
+ if ((err = mp_read_unsigned_bin(key->qP, (unsigned char *)qP, qPlen)) != CRYPT_OK) { goto LBL_ERR; }
+ return CRYPT_OK;
+
+LBL_ERR:
+ rsa_free(key);
+ return err;
+}
+
+#endif /* LTC_MRSA */
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/libtomcrypt/src/pk/rsa/rsa_sign_hash.c b/libtomcrypt/src/pk/rsa/rsa_sign_hash.c
index 3b64095..05c7155 100644
--- a/libtomcrypt/src/pk/rsa/rsa_sign_hash.c
+++ b/libtomcrypt/src/pk/rsa/rsa_sign_hash.c
@@ -5,25 +5,23 @@
*
* The library is free for all purposes without any express
* guarantee it works.
- *
- * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
*/
#include "tomcrypt.h"
/**
@file rsa_sign_hash.c
- RSA LTC_PKCS #1 v1.5 and v2 PSS sign hash, Tom St Denis and Andreas Lange
+ RSA PKCS #1 v1.5 and v2 PSS sign hash, Tom St Denis and Andreas Lange
*/
#ifdef LTC_MRSA
/**
- LTC_PKCS #1 pad then sign
+ PKCS #1 pad then sign
@param in The hash to sign
@param inlen The length of the hash to sign (octets)
@param out [out] The signature
@param outlen [in/out] The max size and resulting size of the signature
- @param padding Type of padding (LTC_LTC_PKCS_1_PSS or LTC_LTC_PKCS_1_V1_5)
+ @param padding Type of padding (LTC_PKCS_1_PSS, LTC_PKCS_1_V1_5 or LTC_PKCS_1_V1_5_NA1)
@param prng An active PRNG state
@param prng_idx The index of the PRNG desired
@param hash_idx The index of the hash desired
@@ -47,15 +45,21 @@ int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen,
LTC_ARGCHK(key != NULL);
/* valid padding? */
- if ((padding != LTC_LTC_PKCS_1_V1_5) && (padding != LTC_LTC_PKCS_1_PSS)) {
+ if ((padding != LTC_PKCS_1_V1_5) &&
+ (padding != LTC_PKCS_1_PSS) &&
+ (padding != LTC_PKCS_1_V1_5_NA1)) {
return CRYPT_PK_INVALID_PADDING;
}
- if (padding == LTC_LTC_PKCS_1_PSS) {
- /* valid prng and hash ? */
+ if (padding == LTC_PKCS_1_PSS) {
+ /* valid prng ? */
if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
return err;
}
+ }
+
+ if (padding != LTC_PKCS_1_V1_5_NA1) {
+ /* valid hash ? */
if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
return err;
}
@@ -71,7 +75,7 @@ int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen,
return CRYPT_BUFFER_OVERFLOW;
}
- if (padding == LTC_LTC_PKCS_1_PSS) {
+ if (padding == LTC_PKCS_1_PSS) {
/* PSS pad the key */
x = *outlen;
if ((err = pkcs_1_pss_encode(in, inlen, saltlen, prng, prng_idx,
@@ -79,48 +83,56 @@ int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen,
return err;
}
} else {
- /* LTC_PKCS #1 v1.5 pad the hash */
+ /* PKCS #1 v1.5 pad the hash */
unsigned char *tmpin;
- ltc_asn1_list digestinfo[2], siginfo[2];
- /* not all hashes have OIDs... so sad */
- if (hash_descriptor[hash_idx].OIDlen == 0) {
- return CRYPT_INVALID_ARG;
- }
+ if (padding == LTC_PKCS_1_V1_5) {
+ ltc_asn1_list digestinfo[2], siginfo[2];
+ /* not all hashes have OIDs... so sad */
+ if (hash_descriptor[hash_idx].OIDlen == 0) {
+ return CRYPT_INVALID_ARG;
+ }
- /* construct the SEQUENCE
- SEQUENCE {
- SEQUENCE {hashoid OID
- blah NULL
- }
- hash OCTET STRING
+ /* construct the SEQUENCE
+ SEQUENCE {
+ SEQUENCE {hashoid OID
+ blah NULL
+ }
+ hash OCTET STRING
+ }
+ */
+ LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash_idx].OID, hash_descriptor[hash_idx].OIDlen);
+ LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0);
+ LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2);
+ LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, in, inlen);
+
+ /* allocate memory for the encoding */
+ y = mp_unsigned_bin_size(key->N);
+ tmpin = XMALLOC(y);
+ if (tmpin == NULL) {
+ return CRYPT_MEM;
}
- */
- LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash_idx].OID, hash_descriptor[hash_idx].OIDlen);
- LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0);
- LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2);
- LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, in, inlen);
-
- /* allocate memory for the encoding */
- y = mp_unsigned_bin_size(key->N);
- tmpin = XMALLOC(y);
- if (tmpin == NULL) {
- return CRYPT_MEM;
- }
- if ((err = der_encode_sequence(siginfo, 2, tmpin, &y)) != CRYPT_OK) {
- XFREE(tmpin);
- return err;
+ if ((err = der_encode_sequence(siginfo, 2, tmpin, &y)) != CRYPT_OK) {
+ XFREE(tmpin);
+ return err;
+ }
+ } else {
+ /* set the pointer and data-length to the input values */
+ tmpin = (unsigned char *)in;
+ y = inlen;
}
x = *outlen;
- if ((err = pkcs_1_v1_5_encode(tmpin, y, LTC_LTC_PKCS_1_EMSA,
- modulus_bitlen, NULL, 0,
- out, &x)) != CRYPT_OK) {
+ err = pkcs_1_v1_5_encode(tmpin, y, LTC_PKCS_1_EMSA, modulus_bitlen, NULL, 0, out, &x);
+
+ if (padding == LTC_PKCS_1_V1_5) {
XFREE(tmpin);
+ }
+
+ if (err != CRYPT_OK) {
return err;
}
- XFREE(tmpin);
}
/* RSA encode it */
@@ -129,6 +141,6 @@ int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen,
#endif /* LTC_MRSA */
-/* $Source$ */
-/* $Revision$ */
-/* $Date$ */
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/libtomcrypt/src/pk/rsa/rsa_sign_saltlen_get.c b/libtomcrypt/src/pk/rsa/rsa_sign_saltlen_get.c
new file mode 100644
index 0000000..b217f94
--- /dev/null
+++ b/libtomcrypt/src/pk/rsa/rsa_sign_saltlen_get.c
@@ -0,0 +1,47 @@
+/* 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.
+ */
+#include "tomcrypt.h"
+
+/**
+ @file rsa_sign_saltlen_get.c
+ Retrieve the maximum size of the salt, Steffen Jaeckel.
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ Retrieve the maximum possible size of the salt when creating a PKCS#1 PSS signature.
+ @param padding Type of padding (LTC_PKCS_1_PSS only)
+ @param hash_idx The index of the desired hash
+ @param key The RSA key
+ @return The maximum salt length in bytes or INT_MAX on error.
+*/
+int rsa_sign_saltlen_get_max_ex(int padding, int hash_idx, rsa_key *key)
+{
+ int ret = INT_MAX;
+ LTC_ARGCHK(key != NULL);
+
+ if ((hash_is_valid(hash_idx) == CRYPT_OK) &&
+ (padding == LTC_PKCS_1_PSS))
+ {
+ ret = rsa_get_size(key);
+ if (ret < INT_MAX)
+ {
+ ret -= (hash_descriptor[hash_idx].hashsize + 2);
+ } /* if */
+ } /* if */
+
+ return ret;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/libtomcrypt/src/pk/rsa/rsa_verify_hash.c b/libtomcrypt/src/pk/rsa/rsa_verify_hash.c
index fe83690..b584696 100644
--- a/libtomcrypt/src/pk/rsa/rsa_verify_hash.c
+++ b/libtomcrypt/src/pk/rsa/rsa_verify_hash.c
@@ -5,25 +5,23 @@
*
* The library is free for all purposes without any express
* guarantee it works.
- *
- * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
*/
#include "tomcrypt.h"
/**
@file rsa_verify_hash.c
- RSA LTC_PKCS #1 v1.5 or v2 PSS signature verification, Tom St Denis and Andreas Lange
+ RSA PKCS #1 v1.5 or v2 PSS signature verification, Tom St Denis and Andreas Lange
*/
#ifdef LTC_MRSA
/**
- LTC_PKCS #1 de-sign then v1.5 or PSS depad
+ PKCS #1 de-sign then v1.5 or PSS depad
@param sig The signature data
@param siglen The length of the signature data (octets)
@param hash The hash of the message that was signed
@param hashlen The length of the hash of the message that was signed (octets)
- @param padding Type of padding (LTC_LTC_PKCS_1_PSS or LTC_LTC_PKCS_1_V1_5)
+ @param padding Type of padding (LTC_PKCS_1_PSS, LTC_PKCS_1_V1_5 or LTC_PKCS_1_V1_5_NA1)
@param hash_idx The index of the desired hash
@param saltlen The length of the salt used during signature
@param stat [out] The result of the signature comparison, 1==valid, 0==invalid
@@ -50,12 +48,13 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
/* valid padding? */
- if ((padding != LTC_LTC_PKCS_1_V1_5) &&
- (padding != LTC_LTC_PKCS_1_PSS)) {
+ if ((padding != LTC_PKCS_1_V1_5) &&
+ (padding != LTC_PKCS_1_PSS) &&
+ (padding != LTC_PKCS_1_V1_5_NA1)) {
return CRYPT_PK_INVALID_PADDING;
}
- if (padding == LTC_LTC_PKCS_1_PSS) {
+ if (padding != LTC_PKCS_1_V1_5_NA1) {
/* valid hash ? */
if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
return err;
@@ -90,21 +89,21 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
return CRYPT_INVALID_PACKET;
}
- if (padding == LTC_LTC_PKCS_1_PSS) {
+ if (padding == LTC_PKCS_1_PSS) {
/* PSS decode and verify it */
- err = pkcs_1_pss_decode(hash, hashlen, tmpbuf, x, saltlen, hash_idx, modulus_bitlen, stat);
+
+ if(modulus_bitlen%8 == 1){
+ err = pkcs_1_pss_decode(hash, hashlen, tmpbuf+1, x-1, saltlen, hash_idx, modulus_bitlen, stat);
+ }
+ else{
+ err = pkcs_1_pss_decode(hash, hashlen, tmpbuf, x, saltlen, hash_idx, modulus_bitlen, stat);
+ }
+
} else {
- /* LTC_PKCS #1 v1.5 decode it */
+ /* PKCS #1 v1.5 decode it */
unsigned char *out;
- unsigned long outlen, loid[16];
+ unsigned long outlen;
int decoded;
- ltc_asn1_list digestinfo[2], siginfo[2];
-
- /* not all hashes have OIDs... so sad */
- if (hash_descriptor[hash_idx].OIDlen == 0) {
- err = CRYPT_INVALID_ARG;
- goto bail_2;
- }
/* allocate temp buffer for decoded hash */
outlen = ((modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0)) - 3;
@@ -114,36 +113,63 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
goto bail_2;
}
- if ((err = pkcs_1_v1_5_decode(tmpbuf, x, LTC_LTC_PKCS_1_EMSA, modulus_bitlen, out, &outlen, &decoded)) != CRYPT_OK) {
- XFREE(out);
+ if ((err = pkcs_1_v1_5_decode(tmpbuf, x, LTC_PKCS_1_EMSA, modulus_bitlen, out, &outlen, &decoded)) != CRYPT_OK) {
+ XFREE(out);
goto bail_2;
}
- /* now we must decode out[0...outlen-1] using ASN.1, test the OID and then test the hash */
- /* construct the SEQUENCE
- SEQUENCE {
- SEQUENCE {hashoid OID
- blah NULL
+ if (padding == LTC_PKCS_1_V1_5) {
+ unsigned long loid[16], reallen;
+ ltc_asn1_list digestinfo[2], siginfo[2];
+
+ /* not all hashes have OIDs... so sad */
+ if (hash_descriptor[hash_idx].OIDlen == 0) {
+ err = CRYPT_INVALID_ARG;
+ goto bail_2;
+ }
+
+ /* now we must decode out[0...outlen-1] using ASN.1, test the OID and then test the hash */
+ /* construct the SEQUENCE
+ SEQUENCE {
+ SEQUENCE {hashoid OID
+ blah NULL
+ }
+ hash OCTET STRING
+ }
+ */
+ LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, loid, sizeof(loid)/sizeof(loid[0]));
+ LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0);
+ LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2);
+ LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, tmpbuf, siglen);
+
+ if ((err = der_decode_sequence(out, outlen, siginfo, 2)) != CRYPT_OK) {
+ /* fallback to Legacy:missing NULL */
+ LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 1);
+ if ((err = der_decode_sequence(out, outlen, siginfo, 2)) != CRYPT_OK) {
+ XFREE(out);
+ goto bail_2;
}
- hash OCTET STRING
}
- */
- LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, loid, sizeof(loid)/sizeof(loid[0]));
- LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0);
- LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2);
- LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, tmpbuf, siglen);
-
- if ((err = der_decode_sequence(out, outlen, siginfo, 2)) != CRYPT_OK) {
- XFREE(out);
- goto bail_2;
- }
- /* test OID */
- if ((digestinfo[0].size == hash_descriptor[hash_idx].OIDlen) &&
+ if ((err = der_length_sequence(siginfo, 2, &reallen)) != CRYPT_OK) {
+ XFREE(out);
+ goto bail_2;
+ }
+
+ /* test OID */
+ if ((reallen == outlen) &&
+ (digestinfo[0].size == hash_descriptor[hash_idx].OIDlen) &&
(XMEMCMP(digestinfo[0].data, hash_descriptor[hash_idx].OID, sizeof(unsigned long) * hash_descriptor[hash_idx].OIDlen) == 0) &&
- (siginfo[1].size == hashlen) &&
+ (siginfo[1].size == hashlen) &&
(XMEMCMP(siginfo[1].data, hash, hashlen) == 0)) {
- *stat = 1;
+ *stat = 1;
+ }
+ } else {
+ /* only check if the hash is equal */
+ if ((hashlen == outlen) &&
+ (XMEMCMP(out, hash, hashlen) == 0)) {
+ *stat = 1;
+ }
}
#ifdef LTC_CLEAN_STACK
@@ -162,6 +188,6 @@ bail_2:
#endif /* LTC_MRSA */
-/* $Source$ */
-/* $Revision$ */
-/* $Date$ */
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */