1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 /**
6   @file rsa_encrypt_key.c
7   RSA PKCS #1 encryption, Tom St Denis and Andreas Lange
8 */
9 
10 #ifdef LTC_MRSA
11 
12 /**
13     (PKCS #1 v2.0) OAEP pad then encrypt
14     @param in          The plaintext
15     @param inlen       The length of the plaintext (octets)
16     @param out         [out] The ciphertext
17     @param outlen      [in/out] The max size and resulting size of the ciphertext
18     @param lparam      The system "lparam" for the encryption
19     @param lparamlen   The length of lparam (octets)
20     @param prng        An active PRNG
21     @param prng_idx    The index of the desired prng
22     @param hash_idx    The index of the desired hash
23     @param padding     Type of padding (LTC_PKCS_1_OAEP or LTC_PKCS_1_V1_5)
24     @param key         The RSA key to encrypt to
25     @return CRYPT_OK if successful
26 */
rsa_encrypt_key_ex(const unsigned char * in,unsigned long inlen,unsigned char * out,unsigned long * outlen,const unsigned char * lparam,unsigned long lparamlen,prng_state * prng,int prng_idx,int hash_idx,int padding,const rsa_key * key)27 int rsa_encrypt_key_ex(const unsigned char *in,       unsigned long  inlen,
28                              unsigned char *out,      unsigned long *outlen,
29                        const unsigned char *lparam,   unsigned long  lparamlen,
30                              prng_state    *prng,     int            prng_idx,
31                              int            hash_idx, int            padding,
32                        const rsa_key       *key)
33 {
34   unsigned long modulus_bitlen, modulus_bytelen, x;
35   int           err;
36 
37   LTC_ARGCHK(in     != NULL);
38   LTC_ARGCHK(out    != NULL);
39   LTC_ARGCHK(outlen != NULL);
40   LTC_ARGCHK(key    != NULL);
41 
42   /* valid padding? */
43   if ((padding != LTC_PKCS_1_V1_5) &&
44       (padding != LTC_PKCS_1_OAEP)) {
45     return CRYPT_PK_INVALID_PADDING;
46   }
47 
48   /* valid prng? */
49   if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
50      return err;
51   }
52 
53   if (padding == LTC_PKCS_1_OAEP) {
54     /* valid hash? */
55     if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
56        return err;
57     }
58   }
59 
60   /* get modulus len in bits */
61   modulus_bitlen = mp_count_bits( (key->N));
62 
63   /* outlen must be at least the size of the modulus */
64   modulus_bytelen = mp_unsigned_bin_size( (key->N));
65   if (modulus_bytelen > *outlen) {
66      *outlen = modulus_bytelen;
67      return CRYPT_BUFFER_OVERFLOW;
68   }
69 
70   if (padding == LTC_PKCS_1_OAEP) {
71     /* OAEP pad the key */
72     x = *outlen;
73     if ((err = pkcs_1_oaep_encode(in, inlen, lparam,
74                                   lparamlen, modulus_bitlen, prng, prng_idx, hash_idx,
75                                   out, &x)) != CRYPT_OK) {
76        return err;
77     }
78   } else {
79     /* PKCS #1 v1.5 pad the key */
80     x = *outlen;
81     if ((err = pkcs_1_v1_5_encode(in, inlen, LTC_PKCS_1_EME,
82                                   modulus_bitlen, prng, prng_idx,
83                                   out, &x)) != CRYPT_OK) {
84       return err;
85     }
86   }
87 
88   /* rsa exptmod the OAEP or PKCS #1 v1.5 pad */
89   return ltc_mp.rsa_me(out, x, out, outlen, PK_PUBLIC, key);
90 }
91 
92 #endif /* LTC_MRSA */
93