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