diff options
-rw-r--r-- | cipher/pubkey-internal.h | 4 | ||||
-rw-r--r-- | cipher/pubkey-util.c | 25 | ||||
-rw-r--r-- | cipher/rsa-common.c | 65 | ||||
-rw-r--r-- | src/cipher.h | 1 | ||||
-rw-r--r-- | tests/basic.c | 8 |
5 files changed, 103 insertions, 0 deletions
diff --git a/cipher/pubkey-internal.h b/cipher/pubkey-internal.h index 193248c3..b8167c77 100644 --- a/cipher/pubkey-internal.h +++ b/cipher/pubkey-internal.h @@ -56,6 +56,10 @@ gpg_err_code_t _gcry_rsa_pkcs1_decode_for_enc (unsigned char **r_result, size_t *r_resultlen, unsigned int nbits, gcry_mpi_t value); gpg_err_code_t +_gcry_rsa_pkcs1_encode_raw_for_sig (gcry_mpi_t *r_result, unsigned int nbits, + const unsigned char *value, size_t valuelen); + +gpg_err_code_t _gcry_rsa_pkcs1_encode_for_sig (gcry_mpi_t *r_result, unsigned int nbits, const unsigned char *value, size_t valuelen, int algo); diff --git a/cipher/pubkey-util.c b/cipher/pubkey-util.c index 616b4990..514f1eb5 100644 --- a/cipher/pubkey-util.c +++ b/cipher/pubkey-util.c @@ -142,6 +142,16 @@ _gcry_pk_util_parse_flaglist (gcry_sexp_t list, rc = GPG_ERR_INV_FLAG; break; + case 9: + if (!memcmp (s, "pkcs1-raw", 9) && encoding == PUBKEY_ENC_UNKNOWN) + { + encoding = PUBKEY_ENC_PKCS1_RAW; + flags |= PUBKEY_FLAG_FIXEDLEN; + } + else if (!igninvflag) + rc = GPG_ERR_INV_FLAG; + break; + case 10: if (!memcmp (s, "igninvflag", 10)) igninvflag = 1; @@ -850,6 +860,21 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi, ctx->hash_algo); } } + else if (ctx->encoding == PUBKEY_ENC_PKCS1_RAW && lvalue + && (ctx->op == PUBKEY_OP_SIGN || ctx->op == PUBKEY_OP_VERIFY)) + { + const void * value; + size_t valuelen; + + if (sexp_length (lvalue) != 2) + rc = GPG_ERR_INV_OBJ; + else if ( !(value=sexp_nth_data (lvalue, 1, &valuelen)) + || !valuelen ) + rc = GPG_ERR_INV_OBJ; + else + rc = _gcry_rsa_pkcs1_encode_raw_for_sig (ret_mpi, ctx->nbits, + value, valuelen); + } else if (ctx->encoding == PUBKEY_ENC_OAEP && lvalue && ctx->op == PUBKEY_OP_ENCRYPT) { diff --git a/cipher/rsa-common.c b/cipher/rsa-common.c index 4f5a6594..f56e9896 100644 --- a/cipher/rsa-common.c +++ b/cipher/rsa-common.c @@ -319,6 +319,71 @@ _gcry_rsa_pkcs1_encode_for_sig (gcry_mpi_t *r_result, unsigned int nbits, return rc; } +/* Encode {VALUE,VALUELEN} for an NBITS keys using the pkcs#1 block + type 1 padding. On success the result is stored as a new MPI at + R_RESULT. On error the value at R_RESULT is undefined. + + We encode the value in this way: + + 0 1 PAD(n bytes) 0 VALUE(valuelen bytes) + + 0 is a marker we unfortunately can't encode because we return an + MPI which strips all leading zeroes. + 1 is the block type. + PAD consists of 0xff bytes. + 0 marks the end of the padding. + + (Note that PGP prior to version 2.3 encoded the message digest as: + 0 1 MD(16 bytes) 0 PAD(n bytes) 1 + The MD is always 16 bytes here because it's always MD5. GnuPG + does not not support pre-v2.3 signatures, but I'm including this + comment so the information is easily found if needed.) +*/ +gpg_err_code_t +_gcry_rsa_pkcs1_encode_raw_for_sig (gcry_mpi_t *r_result, unsigned int nbits, + const unsigned char *value, size_t valuelen) +{ + gcry_err_code_t rc = 0; + gcry_error_t err; + byte *frame = NULL; + size_t nframe = (nbits+7) / 8; + int i; + size_t n; + + if ( !valuelen || valuelen + 4 > nframe) + { + /* Can't encode an DLEN byte digest MD into an NFRAME byte + frame. */ + return GPG_ERR_TOO_SHORT; + } + + if ( !(frame = xtrymalloc (nframe)) ) + return gpg_err_code_from_syserror (); + + /* Assemble the pkcs#1 block type 1. */ + n = 0; + frame[n++] = 0; + frame[n++] = 1; /* block type */ + i = nframe - valuelen - 3 ; + gcry_assert (i > 1); + memset (frame+n, 0xff, i ); + n += i; + frame[n++] = 0; + memcpy (frame+n, value, valuelen ); + n += valuelen; + gcry_assert (n == nframe); + + /* Convert it into an MPI. */ + err = _gcry_mpi_scan (r_result, GCRYMPI_FMT_USG, frame, n, &nframe); + if (err) + rc = gcry_err_code (err); + else if (DBG_CIPHER) + log_mpidump ("PKCS#1 block type 1 encoded data", *r_result); + xfree (frame); + + return rc; +} + /* Mask generation function for OAEP. See RFC-3447 B.2.1. */ static gcry_err_code_t diff --git a/src/cipher.h b/src/cipher.h index 10bfe0c5..26ffddc6 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -54,6 +54,7 @@ enum pk_encoding { PUBKEY_ENC_RAW, PUBKEY_ENC_PKCS1, + PUBKEY_ENC_PKCS1_RAW, PUBKEY_ENC_OAEP, PUBKEY_ENC_PSS, PUBKEY_ENC_UNKNOWN diff --git a/tests/basic.c b/tests/basic.c index 4474a9de..e21e0552 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -5155,6 +5155,10 @@ check_pubkey_sign (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo) " (hash sha1 #11223344556677889900AABBCCDDEEFF10203040#))\n", GCRY_PK_RSA, 0 }, + { "(data\n (flags pkcs1-raw)\n" + " (hash sha1 #11223344556677889900AABBCCDDEEFF10203040#))\n", + GCRY_PK_RSA, + GPG_ERR_CONFLICT }, { "(data\n (flags oaep)\n" " (hash sha1 #11223344556677889900AABBCCDDEEFF10203040#))\n", 0, @@ -5187,6 +5191,10 @@ check_pubkey_sign (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo) " (value #11223344556677889900AA#))\n", GCRY_PK_RSA, GPG_ERR_CONFLICT }, + { "(data\n (flags pkcs1-raw)\n" + " (value #11223344556677889900AA#))\n", + GCRY_PK_RSA, + 0 }, { "(data\n (flags raw foo)\n" " (value #11223344556677889900AA#))\n", 0, |