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