1 // SPDX-License-Identifier: BSD-2-Clause
2 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3  *
4  * LibTomCrypt is a library that provides various cryptographic
5  * algorithms in a highly modular and flexible manner.
6  *
7  * The library is free for all purposes without any express
8  * guarantee it works.
9  */
10 #include "tomcrypt_private.h"
11 
12 #ifdef LTC_PADDING
13 
14 /**
15    Determine the to-be-padded length.
16 
17    @param length     [in/out] The size of the data before/after padding
18    @param mode       Mask of (LTC_PAD_xxx | block_length)
19    @return CRYPT_OK on success
20 */
_padding_padded_length(unsigned long * length,unsigned long mode)21 static int _padding_padded_length(unsigned long *length, unsigned long mode)
22 {
23    enum padding_type padding;
24    unsigned char pad, block_length, r, t;
25 
26    LTC_ARGCHK(length != NULL);
27 
28    block_length = mode & 0xff;
29    padding = mode & LTC_PAD_MASK;
30    r = *length % block_length;
31 
32    switch (padding) {
33       case LTC_PAD_ZERO:
34          if (r == 0) {
35             t = 0;
36             break;
37          }
38          /* FALLTHROUGH */
39       case LTC_PAD_PKCS7:
40       case LTC_PAD_ONE_AND_ZERO:
41       case LTC_PAD_ZERO_ALWAYS:
42          t = 1;
43          break;
44 #ifdef LTC_RNG_GET_BYTES
45       case LTC_PAD_ISO_10126:
46          do {
47             if (rng_get_bytes(&t, sizeof(t), NULL) != sizeof(t)) {
48                return CRYPT_ERROR_READPRNG;
49             }
50             t %= (256 / block_length);
51          } while (t == 0);
52          break;
53 #endif
54       case LTC_PAD_ANSI_X923:
55          if (block_length != 16) {
56             return CRYPT_INVALID_ARG;
57          }
58          t = 1;
59          break;
60       default:
61          return CRYPT_INVALID_ARG;
62    }
63 
64    pad = (t * block_length) - r;
65 
66    if ((pad == 0) && (padding != LTC_PAD_ZERO)) {
67       pad = block_length;
68    }
69 
70    *length += pad;
71 
72    return CRYPT_OK;
73 }
74 
75 /**
76    Add padding to data.
77 
78       This pads your data.
79 
80    @param data          The data to depad
81    @param length        The size of the data before padding
82    @param padded_length [in/out] The size of the data available/after padding
83    @param mode          One of the LTC_PAD_xx flags
84    @return CRYPT_OK on success
85 */
padding_pad(unsigned char * data,unsigned long length,unsigned long * padded_length,unsigned long mode)86 int padding_pad(unsigned char *data, unsigned long length, unsigned long* padded_length, unsigned long mode)
87 {
88    unsigned long diff, l;
89    enum padding_type type;
90    int err;
91 
92    LTC_ARGCHK(data          != NULL);
93    LTC_ARGCHK(padded_length != NULL);
94 
95    l = length;
96    if ((err = _padding_padded_length(&l, mode)) != CRYPT_OK) {
97       return err;
98    }
99 
100    type = mode & LTC_PAD_MASK;
101 
102    if (*padded_length < l) {
103 #ifdef LTC_RNG_GET_BYTES
104       if (type != LTC_PAD_ISO_10126) {
105          *padded_length = l;
106       } else {
107          *padded_length = length + 256;
108       }
109 #else
110       *padded_length = l;
111 #endif
112       return CRYPT_BUFFER_OVERFLOW;
113    }
114 
115    diff = l - length;
116    if (diff > 255) return CRYPT_INVALID_ARG;
117 
118    switch (type) {
119       case LTC_PAD_PKCS7:
120          XMEMSET(&data[length], diff, diff);
121          break;
122 #ifdef LTC_RNG_GET_BYTES
123       case LTC_PAD_ISO_10126:
124          if (rng_get_bytes(&data[length], diff-1, NULL) != diff-1) {
125             return CRYPT_ERROR_READPRNG;
126          }
127          data[l-1] =  diff;
128          break;
129 #endif
130       case LTC_PAD_ANSI_X923:
131          XMEMSET(&data[length], 0, diff-1);
132          data[l-1] =  diff;
133          break;
134       case LTC_PAD_ONE_AND_ZERO:
135          XMEMSET(&data[length + 1], 0, diff);
136          data[length] =  0x80;
137          break;
138       case LTC_PAD_ZERO:
139       case LTC_PAD_ZERO_ALWAYS:
140          XMEMSET(&data[length], 0, diff);
141          break;
142       default:
143          return CRYPT_INVALID_ARG;
144    }
145    *padded_length = l;
146 
147    return CRYPT_OK;
148 }
149 
150 #endif
151 
152 /* ref:         $Format:%D$ */
153 /* git commit:  $Format:%H$ */
154 /* commit time: $Format:%ai$ */
155