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