| 1 | |
|---|
| 2 | |
|---|
| 3 | |
|---|
| 4 | |
|---|
| 5 | |
|---|
| 6 | |
|---|
| 7 | |
|---|
| 8 | |
|---|
| 9 | |
|---|
| 10 | |
|---|
| 11 | |
|---|
| 12 | |
|---|
| 13 | |
|---|
| 14 | |
|---|
| 15 | |
|---|
| 16 | |
|---|
| 17 | |
|---|
| 18 | |
|---|
| 19 | |
|---|
| 20 | |
|---|
| 21 | |
|---|
| 22 | #include "internal.h" |
|---|
| 23 | #include <string.h> |
|---|
| 24 | #include <stdlib.h> |
|---|
| 25 | |
|---|
| 26 | |
|---|
| 27 | |
|---|
| 28 | |
|---|
| 29 | |
|---|
| 30 | |
|---|
| 31 | static const u8 hdr_md5[] = { |
|---|
| 32 | 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, |
|---|
| 33 | 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 |
|---|
| 34 | }; |
|---|
| 35 | static const u8 hdr_sha1[] = { |
|---|
| 36 | 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, |
|---|
| 37 | 0x05, 0x00, 0x04, 0x14 |
|---|
| 38 | }; |
|---|
| 39 | static const u8 hdr_sha256[] = { |
|---|
| 40 | 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, |
|---|
| 41 | 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 |
|---|
| 42 | }; |
|---|
| 43 | static const u8 hdr_sha384[] = { |
|---|
| 44 | 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, |
|---|
| 45 | 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30 |
|---|
| 46 | }; |
|---|
| 47 | static const u8 hdr_sha512[] = { |
|---|
| 48 | 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, |
|---|
| 49 | 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40 |
|---|
| 50 | }; |
|---|
| 51 | static const u8 hdr_sha224[] = { |
|---|
| 52 | 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, |
|---|
| 53 | 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c |
|---|
| 54 | }; |
|---|
| 55 | static const u8 hdr_ripemd160[] = { |
|---|
| 56 | 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, 0x02, 0x01, |
|---|
| 57 | 0x05, 0x00, 0x04, 0x14 |
|---|
| 58 | }; |
|---|
| 59 | |
|---|
| 60 | |
|---|
| 61 | static const struct digest_info_prefix { |
|---|
| 62 | unsigned int algorithm; |
|---|
| 63 | const u8 * hdr; |
|---|
| 64 | size_t hdr_len; |
|---|
| 65 | size_t hash_len; |
|---|
| 66 | } digest_info_prefix[] = { |
|---|
| 67 | { SC_ALGORITHM_RSA_HASH_NONE, NULL, 0, 0 }, |
|---|
| 68 | { SC_ALGORITHM_RSA_HASH_MD5, hdr_md5, sizeof(hdr_md5), 16 }, |
|---|
| 69 | { SC_ALGORITHM_RSA_HASH_SHA1, hdr_sha1, sizeof(hdr_sha1), 20 }, |
|---|
| 70 | { SC_ALGORITHM_RSA_HASH_SHA256, hdr_sha256, sizeof(hdr_sha256), 32 }, |
|---|
| 71 | { SC_ALGORITHM_RSA_HASH_SHA384, hdr_sha384, sizeof(hdr_sha384), 48 }, |
|---|
| 72 | { SC_ALGORITHM_RSA_HASH_SHA512, hdr_sha512, sizeof(hdr_sha512), 64 }, |
|---|
| 73 | { SC_ALGORITHM_RSA_HASH_SHA224, hdr_sha224, sizeof(hdr_sha224), 28 }, |
|---|
| 74 | { SC_ALGORITHM_RSA_HASH_RIPEMD160,hdr_ripemd160, sizeof(hdr_ripemd160), 20 }, |
|---|
| 75 | { SC_ALGORITHM_RSA_HASH_MD5_SHA1, NULL, 0, 36 }, |
|---|
| 76 | { 0, NULL, 0, 0 } |
|---|
| 77 | }; |
|---|
| 78 | |
|---|
| 79 | |
|---|
| 80 | |
|---|
| 81 | static int sc_pkcs1_add_01_padding(const u8 *in, size_t in_len, |
|---|
| 82 | u8 *out, size_t *out_len, size_t mod_length) |
|---|
| 83 | { |
|---|
| 84 | size_t i; |
|---|
| 85 | |
|---|
| 86 | if (*out_len < mod_length) |
|---|
| 87 | return SC_ERROR_BUFFER_TOO_SMALL; |
|---|
| 88 | if (in_len + 11 > mod_length) |
|---|
| 89 | return SC_ERROR_INVALID_ARGUMENTS; |
|---|
| 90 | i = mod_length - in_len; |
|---|
| 91 | memmove(out + i, in, in_len); |
|---|
| 92 | *out++ = 0x00; |
|---|
| 93 | *out++ = 0x01; |
|---|
| 94 | |
|---|
| 95 | memset(out, 0xFF, i - 3); |
|---|
| 96 | out += i - 3; |
|---|
| 97 | *out = 0x00; |
|---|
| 98 | |
|---|
| 99 | *out_len = mod_length; |
|---|
| 100 | return SC_SUCCESS; |
|---|
| 101 | } |
|---|
| 102 | |
|---|
| 103 | int sc_pkcs1_strip_01_padding(const u8 *in_dat, size_t in_len, |
|---|
| 104 | u8 *out, size_t *out_len) |
|---|
| 105 | { |
|---|
| 106 | const u8 *tmp = in_dat; |
|---|
| 107 | size_t len; |
|---|
| 108 | |
|---|
| 109 | if (in_dat == NULL || in_len < 10) |
|---|
| 110 | return SC_ERROR_INTERNAL; |
|---|
| 111 | |
|---|
| 112 | if (*tmp == 0) { |
|---|
| 113 | tmp++; |
|---|
| 114 | in_len--; |
|---|
| 115 | } |
|---|
| 116 | len = in_len; |
|---|
| 117 | if (*tmp != 0x01) |
|---|
| 118 | return SC_ERROR_WRONG_PADDING; |
|---|
| 119 | for (tmp++, len--; *tmp == 0xff && len != 0; tmp++, len--) |
|---|
| 120 | ; |
|---|
| 121 | if (!len || (in_len - len) < 9 || *tmp++ != 0x00) |
|---|
| 122 | return SC_ERROR_WRONG_PADDING; |
|---|
| 123 | len--; |
|---|
| 124 | if (out == NULL) |
|---|
| 125 | |
|---|
| 126 | return SC_SUCCESS; |
|---|
| 127 | if (*out_len < len) |
|---|
| 128 | return SC_ERROR_INTERNAL; |
|---|
| 129 | memmove(out, tmp, len); |
|---|
| 130 | *out_len = len; |
|---|
| 131 | return SC_SUCCESS; |
|---|
| 132 | } |
|---|
| 133 | |
|---|
| 134 | |
|---|
| 135 | |
|---|
| 136 | int sc_pkcs1_strip_02_padding(const u8 *data, size_t len, u8 *out, |
|---|
| 137 | size_t *out_len) |
|---|
| 138 | { |
|---|
| 139 | unsigned int n = 0; |
|---|
| 140 | |
|---|
| 141 | if (data == NULL || len < 3) |
|---|
| 142 | return SC_ERROR_INTERNAL; |
|---|
| 143 | |
|---|
| 144 | if (*data == 0) { |
|---|
| 145 | data++; |
|---|
| 146 | len--; |
|---|
| 147 | } |
|---|
| 148 | if (data[0] != 0x02) |
|---|
| 149 | return SC_ERROR_WRONG_PADDING; |
|---|
| 150 | |
|---|
| 151 | for (n = 1; n < len && data[n]; n++) |
|---|
| 152 | ; |
|---|
| 153 | |
|---|
| 154 | if (n >= len || n < 9) |
|---|
| 155 | return SC_ERROR_WRONG_PADDING; |
|---|
| 156 | n++; |
|---|
| 157 | if (out == NULL) |
|---|
| 158 | |
|---|
| 159 | return SC_SUCCESS; |
|---|
| 160 | |
|---|
| 161 | if (*out_len < len - n) |
|---|
| 162 | return SC_ERROR_INTERNAL; |
|---|
| 163 | memmove(out, data + n, len - n); |
|---|
| 164 | return len - n; |
|---|
| 165 | } |
|---|
| 166 | |
|---|
| 167 | |
|---|
| 168 | static int sc_pkcs1_add_digest_info_prefix(unsigned int algorithm, |
|---|
| 169 | const u8 *in, size_t in_len, u8 *out, size_t *out_len) |
|---|
| 170 | { |
|---|
| 171 | int i; |
|---|
| 172 | |
|---|
| 173 | for (i = 0; digest_info_prefix[i].algorithm != 0; i++) { |
|---|
| 174 | if (algorithm == digest_info_prefix[i].algorithm) { |
|---|
| 175 | const u8 *hdr = digest_info_prefix[i].hdr; |
|---|
| 176 | size_t hdr_len = digest_info_prefix[i].hdr_len, |
|---|
| 177 | hash_len = digest_info_prefix[i].hash_len; |
|---|
| 178 | if (in_len != hash_len || |
|---|
| 179 | *out_len < (hdr_len + hash_len)) |
|---|
| 180 | return SC_ERROR_INTERNAL; |
|---|
| 181 | memmove(out + hdr_len, in, hash_len); |
|---|
| 182 | memmove(out, hdr, hdr_len); |
|---|
| 183 | *out_len = hdr_len + hash_len; |
|---|
| 184 | return SC_SUCCESS; |
|---|
| 185 | } |
|---|
| 186 | } |
|---|
| 187 | |
|---|
| 188 | return SC_ERROR_INTERNAL; |
|---|
| 189 | } |
|---|
| 190 | |
|---|
| 191 | int sc_pkcs1_strip_digest_info_prefix(unsigned int *algorithm, |
|---|
| 192 | const u8 *in_dat, size_t in_len, u8 *out_dat, size_t *out_len) |
|---|
| 193 | { |
|---|
| 194 | int i; |
|---|
| 195 | |
|---|
| 196 | for (i = 0; digest_info_prefix[i].algorithm != 0; i++) { |
|---|
| 197 | size_t hdr_len = digest_info_prefix[i].hdr_len, |
|---|
| 198 | hash_len = digest_info_prefix[i].hash_len; |
|---|
| 199 | const u8 *hdr = digest_info_prefix[i].hdr; |
|---|
| 200 | |
|---|
| 201 | if (in_len == (hdr_len + hash_len) && |
|---|
| 202 | !memcmp(in_dat, hdr, hdr_len)) { |
|---|
| 203 | if (algorithm) |
|---|
| 204 | *algorithm = digest_info_prefix[i].algorithm; |
|---|
| 205 | if (out_dat == NULL) |
|---|
| 206 | |
|---|
| 207 | return SC_SUCCESS; |
|---|
| 208 | if (*out_len < hash_len) |
|---|
| 209 | return SC_ERROR_INTERNAL; |
|---|
| 210 | memmove(out_dat, in_dat + hdr_len, hash_len); |
|---|
| 211 | *out_len = hash_len; |
|---|
| 212 | return SC_SUCCESS; |
|---|
| 213 | } |
|---|
| 214 | } |
|---|
| 215 | return SC_ERROR_INTERNAL; |
|---|
| 216 | } |
|---|
| 217 | |
|---|
| 218 | |
|---|
| 219 | int sc_pkcs1_encode(sc_context_t *ctx, unsigned long flags, |
|---|
| 220 | const u8 *in, size_t in_len, u8 *out, size_t *out_len, size_t mod_len) |
|---|
| 221 | { |
|---|
| 222 | int i; |
|---|
| 223 | size_t tmp_len = *out_len; |
|---|
| 224 | const u8 *tmp = in; |
|---|
| 225 | unsigned int hash_algo, pad_algo; |
|---|
| 226 | |
|---|
| 227 | hash_algo = flags & (SC_ALGORITHM_RSA_HASHES | SC_ALGORITHM_RSA_HASH_NONE); |
|---|
| 228 | pad_algo = flags & SC_ALGORITHM_RSA_PADS; |
|---|
| 229 | |
|---|
| 230 | if (hash_algo != SC_ALGORITHM_RSA_HASH_NONE) { |
|---|
| 231 | i = sc_pkcs1_add_digest_info_prefix(hash_algo, in, in_len, |
|---|
| 232 | out, &tmp_len); |
|---|
| 233 | if (i != SC_SUCCESS) { |
|---|
| 234 | sc_error(ctx, "Unable to add digest info 0x%x\n", |
|---|
| 235 | hash_algo); |
|---|
| 236 | return i; |
|---|
| 237 | } |
|---|
| 238 | tmp = out; |
|---|
| 239 | } else |
|---|
| 240 | tmp_len = in_len; |
|---|
| 241 | |
|---|
| 242 | switch(pad_algo) { |
|---|
| 243 | case SC_ALGORITHM_RSA_PAD_NONE: |
|---|
| 244 | |
|---|
| 245 | if (out != tmp) |
|---|
| 246 | memcpy(out, tmp, tmp_len); |
|---|
| 247 | *out_len = tmp_len; |
|---|
| 248 | return SC_SUCCESS; |
|---|
| 249 | case SC_ALGORITHM_RSA_PAD_PKCS1: |
|---|
| 250 | |
|---|
| 251 | return sc_pkcs1_add_01_padding(tmp, tmp_len, out, out_len, |
|---|
| 252 | mod_len); |
|---|
| 253 | default: |
|---|
| 254 | |
|---|
| 255 | sc_error(ctx, "Unsupported padding algorithm 0x%x\n", pad_algo); |
|---|
| 256 | return SC_ERROR_NOT_SUPPORTED; |
|---|
| 257 | } |
|---|
| 258 | } |
|---|
| 259 | |
|---|
| 260 | int sc_get_encoding_flags(sc_context_t *ctx, |
|---|
| 261 | unsigned long iflags, unsigned long caps, |
|---|
| 262 | unsigned long *pflags, unsigned long *sflags) |
|---|
| 263 | { |
|---|
| 264 | size_t i; |
|---|
| 265 | |
|---|
| 266 | if (pflags == NULL || sflags == NULL) |
|---|
| 267 | return SC_ERROR_INVALID_ARGUMENTS; |
|---|
| 268 | |
|---|
| 269 | for (i = 0; digest_info_prefix[i].algorithm != 0; i++) { |
|---|
| 270 | if (iflags & digest_info_prefix[i].algorithm) { |
|---|
| 271 | if (digest_info_prefix[i].algorithm != SC_ALGORITHM_RSA_HASH_NONE && |
|---|
| 272 | caps & digest_info_prefix[i].algorithm) |
|---|
| 273 | *sflags |= digest_info_prefix[i].algorithm; |
|---|
| 274 | else |
|---|
| 275 | *pflags |= digest_info_prefix[i].algorithm; |
|---|
| 276 | break; |
|---|
| 277 | } |
|---|
| 278 | } |
|---|
| 279 | |
|---|
| 280 | if (iflags & SC_ALGORITHM_RSA_PAD_PKCS1) { |
|---|
| 281 | if (caps & SC_ALGORITHM_RSA_PAD_PKCS1) |
|---|
| 282 | *sflags |= SC_ALGORITHM_RSA_PAD_PKCS1; |
|---|
| 283 | else |
|---|
| 284 | *pflags |= SC_ALGORITHM_RSA_PAD_PKCS1; |
|---|
| 285 | } else if ((iflags & SC_ALGORITHM_RSA_PADS) == SC_ALGORITHM_RSA_PAD_NONE) { |
|---|
| 286 | if (!(caps & SC_ALGORITHM_RSA_RAW)) { |
|---|
| 287 | sc_error(ctx, "raw RSA is not supported"); |
|---|
| 288 | return SC_ERROR_NOT_SUPPORTED; |
|---|
| 289 | } |
|---|
| 290 | *sflags |= SC_ALGORITHM_RSA_RAW; |
|---|
| 291 | |
|---|
| 292 | *pflags = 0; |
|---|
| 293 | } else { |
|---|
| 294 | sc_error(ctx, "unsupported algorithm"); |
|---|
| 295 | return SC_ERROR_NOT_SUPPORTED; |
|---|
| 296 | } |
|---|
| 297 | |
|---|
| 298 | return SC_SUCCESS; |
|---|
| 299 | } |
|---|