From 2d8a41805936ce790256c0c0a4c4c0005abe318e Mon Sep 17 00:00:00 2001 From: Andreas Steffen Date: Sun, 7 Oct 2007 21:43:24 +0000 Subject: [PATCH] added eme_pkcs1_decrypt() method --- .../crypto/rsa/rsa_private_key.c | 83 +++++++++++++++---- .../crypto/rsa/rsa_private_key.h | 15 ++++ 2 files changed, 80 insertions(+), 18 deletions(-) diff --git a/src/libstrongswan/crypto/rsa/rsa_private_key.c b/src/libstrongswan/crypto/rsa/rsa_private_key.c index a70518129..0fb3d12b6 100644 --- a/src/libstrongswan/crypto/rsa/rsa_private_key.c +++ b/src/libstrongswan/crypto/rsa/rsa_private_key.c @@ -19,6 +19,8 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. + * + * RCSID $Id$ */ #include @@ -29,6 +31,7 @@ #include "rsa_public_key.h" #include "rsa_private_key.h" +#include #include #include #include @@ -140,23 +143,23 @@ struct private_rsa_private_key_t { /* ASN.1 definition of a PKCS#1 RSA private key */ static const asn1Object_t privkey_objects[] = { - { 0, "RSAPrivateKey", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */ - { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 2 */ - { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 3 */ - { 1, "privateExponent", ASN1_INTEGER, ASN1_BODY }, /* 4 */ - { 1, "prime1", ASN1_INTEGER, ASN1_BODY }, /* 5 */ - { 1, "prime2", ASN1_INTEGER, ASN1_BODY }, /* 6 */ - { 1, "exponent1", ASN1_INTEGER, ASN1_BODY }, /* 7 */ - { 1, "exponent2", ASN1_INTEGER, ASN1_BODY }, /* 8 */ - { 1, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 9 */ - { 1, "otherPrimeInfos", ASN1_SEQUENCE, ASN1_OPT | - ASN1_LOOP }, /* 10 */ - { 2, "otherPrimeInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 11 */ - { 3, "prime", ASN1_INTEGER, ASN1_BODY }, /* 12 */ - { 3, "exponent", ASN1_INTEGER, ASN1_BODY }, /* 13 */ - { 3, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 14 */ - { 1, "end opt or loop", ASN1_EOC, ASN1_END } /* 15 */ + { 0, "RSAPrivateKey", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ + { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */ + { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 2 */ + { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 3 */ + { 1, "privateExponent", ASN1_INTEGER, ASN1_BODY }, /* 4 */ + { 1, "prime1", ASN1_INTEGER, ASN1_BODY }, /* 5 */ + { 1, "prime2", ASN1_INTEGER, ASN1_BODY }, /* 6 */ + { 1, "exponent1", ASN1_INTEGER, ASN1_BODY }, /* 7 */ + { 1, "exponent2", ASN1_INTEGER, ASN1_BODY }, /* 8 */ + { 1, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 9 */ + { 1, "otherPrimeInfos", ASN1_SEQUENCE, ASN1_OPT | + ASN1_LOOP }, /* 10 */ + { 2, "otherPrimeInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 11 */ + { 3, "prime", ASN1_INTEGER, ASN1_BODY }, /* 12 */ + { 3, "exponent", ASN1_INTEGER, ASN1_BODY }, /* 13 */ + { 3, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 14 */ + { 1, "end opt or loop", ASN1_EOC, ASN1_END } /* 15 */ }; #define PRIV_KEY_VERSION 1 @@ -266,7 +269,50 @@ static chunk_t rsadp(private_rsa_private_key_t *this, chunk_t data) } /** - * Implementation of rsa_private_key.build_emsa_signature. + * Implementation of rsa_private_key_t.eme_pkcs1_decrypt. + */ +static status_t eme_pkcs1_decrypt(private_rsa_private_key_t *this, + chunk_t in, chunk_t *out) +{ + status_t status = FAILED; + chunk_t em, em_ori; + + /* decrypt the input data */ + em = em_ori = this->rsadp(this, in); + + /* PKCS#1 v1.5 EME encryption formatting + * EM = 00 || 02 || PS || 00 || M + * PS = pseudo-random nonzero octets + */ + + /* check for magic bytes */ + if (*(em.ptr) != 0x00 || *(em.ptr+1) != 0x02) + { + DBG1("incorrect padding - probably wrong RSA key"); + goto end; + } + em.ptr += 2; + em.len -= 2; + + /* the plaintext data starts after first 0x00 byte */ + while (em.len-- > 0 && *em.ptr++ != 0x00); + + if (em.len == 0) + { + DBG1("no plaintext data found"); + goto end; + } + + *out = chunk_clone(em); + status = SUCCESS; + +end: + free(em_ori.ptr); + return status; +} + +/** + * Implementation of rsa_private_key_t.build_emsa_pkcs1_signature. */ static status_t build_emsa_pkcs1_signature(private_rsa_private_key_t *this, hash_algorithm_t hash_algorithm, @@ -501,6 +547,7 @@ static private_rsa_private_key_t *rsa_private_key_create_empty(void) private_rsa_private_key_t *this = malloc_thing(private_rsa_private_key_t); /* public functions */ + this->public.eme_pkcs1_decrypt = (status_t (*) (rsa_private_key_t*,chunk_t,chunk_t*))eme_pkcs1_decrypt; this->public.build_emsa_pkcs1_signature = (status_t (*) (rsa_private_key_t*,hash_algorithm_t,chunk_t,chunk_t*))build_emsa_pkcs1_signature; this->public.save_key = (status_t (*) (rsa_private_key_t*,char*))save_key; this->public.get_public_key = (rsa_public_key_t *(*) (rsa_private_key_t*))get_public_key; diff --git a/src/libstrongswan/crypto/rsa/rsa_private_key.h b/src/libstrongswan/crypto/rsa/rsa_private_key.h index 9e1f516ac..a332cad78 100644 --- a/src/libstrongswan/crypto/rsa/rsa_private_key.h +++ b/src/libstrongswan/crypto/rsa/rsa_private_key.h @@ -19,6 +19,8 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. + * + * RCSID $Id$ */ #ifndef RSA_PRIVATE_KEY_H_ @@ -48,6 +50,19 @@ typedef struct rsa_private_key_t rsa_private_key_t; */ struct rsa_private_key_t { + /** + * @brief Decrypt a data block based on EME-PKCS1 encoding. + * + * + * @param this calling object + * @param data encrypted input data + * @param out decrypted output data + * @return + * - SUCCESS + * - FAILED if padding is not correct + */ + status_t (*eme_pkcs1_decrypt) (rsa_private_key_t *this, chunk_t in, chunk_t *out); + /** * @brief Build a signature over a chunk using EMSA-PKCS1 encoding. *