1 /* 2 * PKCS #1 (RSA Encryption) 3 * Copyright (c) 2006-2014, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "includes.h" 10 11 #include "common.h" 12 #include "crypto/crypto.h" 13 #include "rsa.h" 14 #include "asn1.h" 15 #include "pkcs1.h" 16 17 18 static int pkcs1_generate_encryption_block(u8 block_type, size_t modlen, 19 const u8 *in, size_t inlen, 20 u8 *out, size_t *outlen) 21 { 22 size_t ps_len; 23 u8 *pos; 24 25 /* 26 * PKCS #1 v1.5, 8.1: 27 * 28 * EB = 00 || BT || PS || 00 || D 29 * BT = 00 or 01 for private-key operation; 02 for public-key operation 30 * PS = k-3-||D||; at least eight octets 31 * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero) 32 * k = length of modulus in octets (modlen) 33 */ 34 35 if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) { 36 wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer " 37 "lengths (modlen=%lu outlen=%lu inlen=%lu)", 38 __func__, (unsigned long) modlen, 39 (unsigned long) *outlen, 40 (unsigned long) inlen); 41 return -1; 42 } 43 44 pos = out; 45 *pos++ = 0x00; 46 *pos++ = block_type; /* BT */ 47 ps_len = modlen - inlen - 3; 48 switch (block_type) { 49 case 0: 50 os_memset(pos, 0x00, ps_len); 51 pos += ps_len; 52 break; 53 case 1: 54 os_memset(pos, 0xff, ps_len); 55 pos += ps_len; 56 break; 57 case 2: 58 if (os_get_random(pos, ps_len) < 0) { 59 wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get " 60 "random data for PS", __func__); 61 return -1; 62 } 63 while (ps_len--) { 64 if (*pos == 0x00) 65 *pos = 0x01; 66 pos++; 67 } 68 break; 69 default: 70 wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type " 71 "%d", __func__, block_type); 72 return -1; 73 } 74 *pos++ = 0x00; 75 os_memcpy(pos, in, inlen); /* D */ 76 77 return 0; 78 } 79 80 81 int pkcs1_encrypt(int block_type, struct crypto_rsa_key *key, 82 int use_private, const u8 *in, size_t inlen, 83 u8 *out, size_t *outlen) 84 { 85 size_t modlen; 86 87 modlen = crypto_rsa_get_modulus_len(key); 88 89 if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen, 90 out, outlen) < 0) 91 return -1; 92 93 return crypto_rsa_exptmod(out, modlen, out, outlen, key, use_private); 94 } 95 96 97 int pkcs1_v15_private_key_decrypt(struct crypto_rsa_key *key, 98 const u8 *in, size_t inlen, 99 u8 *out, size_t *outlen) 100 { 101 int res; 102 u8 *pos, *end; 103 104 res = crypto_rsa_exptmod(in, inlen, out, outlen, key, 1); 105 if (res) 106 return res; 107 108 if (*outlen < 2 || out[0] != 0 || out[1] != 2) 109 return -1; 110 111 /* Skip PS (pseudorandom non-zero octets) */ 112 pos = out + 2; 113 end = out + *outlen; 114 while (*pos && pos < end) 115 pos++; 116 if (pos == end) 117 return -1; 118 if (pos - out - 2 < 8) { 119 /* PKCS #1 v1.5, 8.1: At least eight octets long PS */ 120 wpa_printf(MSG_INFO, "LibTomCrypt: Too short padding"); 121 return -1; 122 } 123 pos++; 124 125 *outlen -= pos - out; 126 127 /* Strip PKCS #1 header */ 128 os_memmove(out, pos, *outlen); 129 130 return 0; 131 } 132 133 134 int pkcs1_decrypt_public_key(struct crypto_rsa_key *key, 135 const u8 *crypt, size_t crypt_len, 136 u8 *plain, size_t *plain_len) 137 { 138 size_t len; 139 u8 *pos; 140 141 len = *plain_len; 142 if (crypto_rsa_exptmod(crypt, crypt_len, plain, &len, key, 0) < 0) 143 return -1; 144 145 /* 146 * PKCS #1 v1.5, 8.1: 147 * 148 * EB = 00 || BT || PS || 00 || D 149 * BT = 00 or 01 150 * PS = k-3-||D|| times (00 if BT=00) or (FF if BT=01) 151 * k = length of modulus in octets 152 * 153 * Based on 10.1.3, "The block type shall be 01" for a signature. 154 */ 155 156 if (len < 3 + 8 + 16 /* min hash len */ || 157 plain[0] != 0x00 || plain[1] != 0x01) { 158 wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " 159 "structure"); 160 return -1; 161 } 162 163 pos = plain + 3; 164 /* BT = 01 */ 165 if (plain[2] != 0xff) { 166 wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature " 167 "PS (BT=01)"); 168 return -1; 169 } 170 while (pos < plain + len && *pos == 0xff) 171 pos++; 172 173 if (pos - plain - 2 < 8) { 174 /* PKCS #1 v1.5, 8.1: At least eight octets long PS */ 175 wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature " 176 "padding"); 177 return -1; 178 } 179 180 if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) { 181 wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " 182 "structure (2)"); 183 return -1; 184 } 185 pos++; 186 len -= pos - plain; 187 188 /* Strip PKCS #1 header */ 189 os_memmove(plain, pos, len); 190 *plain_len = len; 191 192 return 0; 193 } 194 195 196 int pkcs1_v15_sig_ver(struct crypto_public_key *pk, 197 const u8 *s, size_t s_len, 198 const struct asn1_oid *hash_alg, 199 const u8 *hash, size_t hash_len) 200 { 201 int res; 202 u8 *decrypted; 203 size_t decrypted_len; 204 const u8 *pos, *end, *next, *da_end; 205 struct asn1_hdr hdr; 206 struct asn1_oid oid; 207 208 decrypted = os_malloc(s_len); 209 if (decrypted == NULL) 210 return -1; 211 decrypted_len = s_len; 212 res = crypto_public_key_decrypt_pkcs1(pk, s, s_len, decrypted, 213 &decrypted_len); 214 if (res < 0) { 215 wpa_printf(MSG_INFO, "PKCS #1: RSA decrypt failed"); 216 os_free(decrypted); 217 return -1; 218 } 219 wpa_hexdump(MSG_DEBUG, "Decrypted(S)", decrypted, decrypted_len); 220 221 /* 222 * PKCS #1 v1.5, 10.1.2: 223 * 224 * DigestInfo ::= SEQUENCE { 225 * digestAlgorithm DigestAlgorithmIdentifier, 226 * digest Digest 227 * } 228 * 229 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier 230 * 231 * Digest ::= OCTET STRING 232 * 233 */ 234 if (asn1_get_next(decrypted, decrypted_len, &hdr) < 0 || 235 hdr.class != ASN1_CLASS_UNIVERSAL || 236 hdr.tag != ASN1_TAG_SEQUENCE) { 237 wpa_printf(MSG_DEBUG, 238 "PKCS #1: Expected SEQUENCE (DigestInfo) - found class %d tag 0x%x", 239 hdr.class, hdr.tag); 240 os_free(decrypted); 241 return -1; 242 } 243 244 pos = hdr.payload; 245 end = pos + hdr.length; 246 247 /* 248 * X.509: 249 * AlgorithmIdentifier ::= SEQUENCE { 250 * algorithm OBJECT IDENTIFIER, 251 * parameters ANY DEFINED BY algorithm OPTIONAL 252 * } 253 */ 254 255 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 256 hdr.class != ASN1_CLASS_UNIVERSAL || 257 hdr.tag != ASN1_TAG_SEQUENCE) { 258 wpa_printf(MSG_DEBUG, 259 "PKCS #1: Expected SEQUENCE (AlgorithmIdentifier) - found class %d tag 0x%x", 260 hdr.class, hdr.tag); 261 os_free(decrypted); 262 return -1; 263 } 264 da_end = hdr.payload + hdr.length; 265 266 if (asn1_get_oid(hdr.payload, hdr.length, &oid, &next)) { 267 wpa_printf(MSG_DEBUG, 268 "PKCS #1: Failed to parse digestAlgorithm"); 269 os_free(decrypted); 270 return -1; 271 } 272 273 if (!asn1_oid_equal(&oid, hash_alg)) { 274 char txt[100], txt2[100]; 275 asn1_oid_to_str(&oid, txt, sizeof(txt)); 276 asn1_oid_to_str(hash_alg, txt2, sizeof(txt2)); 277 wpa_printf(MSG_DEBUG, 278 "PKCS #1: Hash alg OID mismatch: was %s, expected %s", 279 txt, txt2); 280 os_free(decrypted); 281 return -1; 282 } 283 284 /* Digest ::= OCTET STRING */ 285 pos = da_end; 286 end = decrypted + decrypted_len; 287 288 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 289 hdr.class != ASN1_CLASS_UNIVERSAL || 290 hdr.tag != ASN1_TAG_OCTETSTRING) { 291 wpa_printf(MSG_DEBUG, 292 "PKCS #1: Expected OCTETSTRING (Digest) - found class %d tag 0x%x", 293 hdr.class, hdr.tag); 294 os_free(decrypted); 295 return -1; 296 } 297 wpa_hexdump(MSG_MSGDUMP, "PKCS #1: Decrypted Digest", 298 hdr.payload, hdr.length); 299 300 if (hdr.length != hash_len || 301 os_memcmp_const(hdr.payload, hash, hdr.length) != 0) { 302 wpa_printf(MSG_INFO, "PKCS #1: Digest value does not match calculated hash"); 303 os_free(decrypted); 304 return -1; 305 } 306 307 os_free(decrypted); 308 309 if (hdr.payload + hdr.length != end) { 310 wpa_printf(MSG_INFO, 311 "PKCS #1: Extra data after signature - reject"); 312 313 wpa_hexdump(MSG_DEBUG, "PKCS #1: Extra data", 314 hdr.payload + hdr.length, 315 end - hdr.payload - hdr.length); 316 return -1; 317 } 318 319 return 0; 320 } 321