1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4
5 /**
6 @file rsa_sign_hash.c
7 RSA PKCS #1 v1.5 and v2 PSS sign hash, Tom St Denis and Andreas Lange
8 */
9
10 #ifdef LTC_MRSA
11
12 /**
13 PKCS #1 pad then sign
14 @param in The hash to sign
15 @param inlen The length of the hash to sign (octets)
16 @param out [out] The signature
17 @param outlen [in/out] The max size and resulting size of the signature
18 @param padding Type of padding (LTC_PKCS_1_PSS, LTC_PKCS_1_V1_5 or LTC_PKCS_1_V1_5_NA1)
19 @param prng An active PRNG state
20 @param prng_idx The index of the PRNG desired
21 @param hash_idx The index of the hash desired
22 @param saltlen The length of the salt desired (octets)
23 @param key The private RSA key to use
24 @return CRYPT_OK if successful
25 */
rsa_sign_hash_ex(const unsigned char * in,unsigned long inlen,unsigned char * out,unsigned long * outlen,int padding,prng_state * prng,int prng_idx,int hash_idx,unsigned long saltlen,const rsa_key * key)26 int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen,
27 unsigned char *out, unsigned long *outlen,
28 int padding,
29 prng_state *prng, int prng_idx,
30 int hash_idx, unsigned long saltlen,
31 const rsa_key *key)
32 {
33 unsigned long modulus_bitlen, modulus_bytelen, x, y;
34 int err;
35
36 LTC_ARGCHK(in != NULL);
37 LTC_ARGCHK(out != NULL);
38 LTC_ARGCHK(outlen != NULL);
39 LTC_ARGCHK(key != NULL);
40
41 /* valid padding? */
42 if ((padding != LTC_PKCS_1_V1_5) &&
43 (padding != LTC_PKCS_1_PSS) &&
44 (padding != LTC_PKCS_1_V1_5_NA1)) {
45 return CRYPT_PK_INVALID_PADDING;
46 }
47
48 if (padding == LTC_PKCS_1_PSS) {
49 /* valid prng ? */
50 if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
51 return err;
52 }
53 }
54
55 if (padding != LTC_PKCS_1_V1_5_NA1) {
56 /* valid hash ? */
57 if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
58 return err;
59 }
60 }
61
62 /* get modulus len in bits */
63 modulus_bitlen = mp_count_bits((key->N));
64
65 /* outlen must be at least the size of the modulus */
66 modulus_bytelen = mp_unsigned_bin_size((key->N));
67 if (modulus_bytelen > *outlen) {
68 *outlen = modulus_bytelen;
69 return CRYPT_BUFFER_OVERFLOW;
70 }
71
72 if (padding == LTC_PKCS_1_PSS) {
73 /* PSS pad the key */
74 x = *outlen;
75 if ((err = pkcs_1_pss_encode(in, inlen, saltlen, prng, prng_idx,
76 hash_idx, modulus_bitlen, out, &x)) != CRYPT_OK) {
77 return err;
78 }
79 } else {
80 /* PKCS #1 v1.5 pad the hash */
81 unsigned char *tmpin;
82
83 if (padding == LTC_PKCS_1_V1_5) {
84 ltc_asn1_list digestinfo[2], siginfo[2];
85 /* not all hashes have OIDs... so sad */
86 if (hash_descriptor[hash_idx]->OIDlen == 0) {
87 return CRYPT_INVALID_ARG;
88 }
89
90 /* construct the SEQUENCE
91 SEQUENCE {
92 SEQUENCE {hashoid OID
93 blah NULL
94 }
95 hash OCTET STRING
96 }
97 */
98 LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash_idx]->OID, hash_descriptor[hash_idx]->OIDlen);
99 LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0);
100 LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2);
101 LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, in, inlen);
102
103 /* allocate memory for the encoding */
104 y = mp_unsigned_bin_size(key->N);
105 tmpin = XMALLOC(y);
106 if (tmpin == NULL) {
107 return CRYPT_MEM;
108 }
109
110 if ((err = der_encode_sequence(siginfo, 2, tmpin, &y)) != CRYPT_OK) {
111 XFREE(tmpin);
112 return err;
113 }
114 } else {
115 /* set the pointer and data-length to the input values */
116 tmpin = (unsigned char *)in;
117 y = inlen;
118 }
119
120 x = *outlen;
121 err = pkcs_1_v1_5_encode(tmpin, y, LTC_PKCS_1_EMSA, modulus_bitlen, NULL, 0, out, &x);
122
123 if (padding == LTC_PKCS_1_V1_5) {
124 XFREE(tmpin);
125 }
126
127 if (err != CRYPT_OK) {
128 return err;
129 }
130 }
131
132 /* RSA encode it */
133 return ltc_mp.rsa_me(out, x, out, outlen, PK_PRIVATE, key);
134 }
135
136 #endif /* LTC_MRSA */
137