1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 /** @file pkcs_1_v1_5_decode.c
6  *
7  *  PKCS #1 v1.5 Padding. (Andreas Lange)
8  */
9 
10 #ifdef LTC_PKCS_1
11 
12 /** @brief PKCS #1 v1.5 decode.
13  *
14  *  @param msg              The encoded data to decode
15  *  @param msglen           The length of the encoded data (octets)
16  *  @param block_type       Block type to use in padding (\sa ltc_pkcs_1_v1_5_blocks)
17  *  @param modulus_bitlen   The bit length of the RSA modulus
18  *  @param out              [out] Destination of decoding
19  *  @param outlen           [in/out] The max size and resulting size of the decoding
20  *  @param is_valid         [out] Boolean whether the padding was valid
21  *
22  *  @return CRYPT_OK if successful
23  */
pkcs_1_v1_5_decode(const unsigned char * msg,unsigned long msglen,int block_type,unsigned long modulus_bitlen,unsigned char * out,unsigned long * outlen,int * is_valid)24 int pkcs_1_v1_5_decode(const unsigned char *msg,
25                              unsigned long  msglen,
26                                        int  block_type,
27                              unsigned long  modulus_bitlen,
28                              unsigned char *out,
29                              unsigned long *outlen,
30                                        int *is_valid)
31 {
32   unsigned long modulus_len, ps_len, i;
33   int result;
34 
35   /* default to invalid packet */
36   *is_valid = 0;
37 
38   modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
39 
40   /* test message size */
41 
42   if ((msglen > modulus_len) || (modulus_len < 11)) {
43     return CRYPT_PK_INVALID_SIZE;
44   }
45 
46   result = CRYPT_OK;
47 
48   /* separate encoded message */
49 
50   if ((msg[0] != 0x00) || (msg[1] != (unsigned char)block_type)) {
51     result = CRYPT_INVALID_PACKET;
52   }
53 
54   if (block_type == LTC_PKCS_1_EME) {
55     for (i = 2; i < modulus_len; i++) {
56       /* separator */
57       if (msg[i] == 0x00) { break; }
58     }
59     ps_len = i++ - 2;
60 
61     if (i >= modulus_len) {
62       /* There was no octet with hexadecimal value 0x00 to separate ps from m.
63        */
64       result = CRYPT_INVALID_PACKET;
65     }
66   } else {
67     for (i = 2; i < modulus_len - 1; i++) {
68        if (msg[i] != 0xFF) { break; }
69     }
70 
71     /* separator check */
72     if (msg[i] != 0) {
73       /* There was no octet with hexadecimal value 0x00 to separate ps from m. */
74       result = CRYPT_INVALID_PACKET;
75     }
76 
77     ps_len = i - 2;
78   }
79 
80   if (ps_len < 8)
81   {
82     /* The length of ps is less than 8 octets.
83      */
84     result = CRYPT_INVALID_PACKET;
85   }
86 
87   if (*outlen < (msglen - (2 + ps_len + 1))) {
88     result = CRYPT_INVALID_PACKET;
89   }
90 
91   if (result == CRYPT_OK) {
92      *outlen = (msglen - (2 + ps_len + 1));
93      XMEMCPY(out, &msg[2 + ps_len + 1], *outlen);
94 
95      /* valid packet */
96      *is_valid = 1;
97   }
98 
99   return result;
100 } /* pkcs_1_v1_5_decode */
101 
102 #endif /* #ifdef LTC_PKCS_1 */
103