18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PKCS #5 (Password-based Encryption) 31b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * Copyright (c) 2009-2015, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/crypto.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/md5.h" 141b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt#include "crypto/sha1.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "asn1.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "pkcs5.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct pkcs5_params { 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum pkcs5_alg { 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PKCS5_ALG_UNKNOWN, 221b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt PKCS5_ALG_MD5_DES_CBC, 231b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt PKCS5_ALG_PBES2, 241b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt PKCS5_ALG_SHA1_3DES_CBC, 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } alg; 261b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt u8 salt[64]; 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t salt_len; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int iter_count; 291b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt enum pbes2_enc_alg { 301b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt PBES2_ENC_ALG_UNKNOWN, 311b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt PBES2_ENC_ALG_DES_EDE3_CBC, 321b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } enc_alg; 331b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt u8 iv[8]; 341b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt size_t iv_len; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 381b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int oid_is_rsadsi(struct asn1_oid *oid) 391b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 401b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return oid->len >= 4 && 411b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[0] == 1 /* iso */ && 421b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[1] == 2 /* member-body */ && 431b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[2] == 840 /* us */ && 441b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[3] == 113549 /* rsadsi */; 451b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 461b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 471b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 481b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int pkcs5_is_oid(struct asn1_oid *oid, unsigned long alg) 491b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 501b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return oid->len == 7 && 511b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid_is_rsadsi(oid) && 521b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[4] == 1 /* pkcs */ && 531b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[5] == 5 /* pkcs-5 */ && 541b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[6] == alg; 551b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 561b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 571b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 581b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int enc_alg_is_oid(struct asn1_oid *oid, unsigned long alg) 591b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 601b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return oid->len == 6 && 611b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid_is_rsadsi(oid) && 621b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[4] == 3 /* encryptionAlgorithm */ && 631b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[5] == alg; 641b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 651b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 661b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 671b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int pkcs12_is_pbe_oid(struct asn1_oid *oid, unsigned long alg) 681b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 691b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return oid->len == 8 && 701b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid_is_rsadsi(oid) && 711b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[4] == 1 /* pkcs */ && 721b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[5] == 12 /* pkcs-12 */ && 731b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[6] == 1 /* pkcs-12PbeIds */ && 741b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt oid->oid[7] == alg; 751b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 761b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 771b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic enum pkcs5_alg pkcs5_get_alg(struct asn1_oid *oid) 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 801b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (pkcs5_is_oid(oid, 3)) /* pbeWithMD5AndDES-CBC (PBES1) */ 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return PKCS5_ALG_MD5_DES_CBC; 821b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (pkcs12_is_pbe_oid(oid, 3)) /* pbeWithSHAAnd3-KeyTripleDES-CBC */ 831b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return PKCS5_ALG_SHA1_3DES_CBC; 841b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (pkcs5_is_oid(oid, 13)) /* id-PBES2 (PBES2) */ 851b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return PKCS5_ALG_PBES2; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return PKCS5_ALG_UNKNOWN; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 901b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int pkcs5_get_params_pbes2(struct pkcs5_params *params, const u8 *pos, 911b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const u8 *enc_alg_end) 921b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 931b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt struct asn1_hdr hdr; 941b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const u8 *end, *kdf_end; 951b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt struct asn1_oid oid; 961b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt char obuf[80]; 971b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 981b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* 991b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * RFC 2898, Ch. A.4 1001b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * 1011b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * PBES2-params ::= SEQUENCE { 1021b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, 1031b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} } 1041b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * 1051b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * PBES2-KDFs ALGORITHM-IDENTIFIER ::= 1061b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * { {PBKDF2-params IDENTIFIED BY id-PBKDF2}, ... } 1071b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt */ 1081b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 1091b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, enc_alg_end - pos, &hdr) < 0 || 1101b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 1111b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 1121b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 1131b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #5: Expected SEQUENCE (PBES2-params) - found class %d tag 0x%x", 1141b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 1151b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 1161b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 1171b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = hdr.payload; 1181b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt end = hdr.payload + hdr.length; 1191b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 1201b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 1211b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 1221b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 1231b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 1241b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #5: Expected SEQUENCE (keyDerivationFunc) - found class %d tag 0x%x", 1251b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 1261b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 1271b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 1281b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 1291b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = hdr.payload; 1301b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt kdf_end = end = hdr.payload + hdr.length; 1311b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 1321b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_oid(pos, end - pos, &oid, &pos)) { 1331b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 1341b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #5: Failed to parse OID (keyDerivationFunc algorithm)"); 1351b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 1361b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 1371b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 1381b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt asn1_oid_to_str(&oid, obuf, sizeof(obuf)); 1391b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #5: PBES2 keyDerivationFunc algorithm %s", 1401b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt obuf); 1411b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (!pkcs5_is_oid(&oid, 12)) /* id-PBKDF2 */ { 1421b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 1431b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #5: Unsupported PBES2 keyDerivationFunc algorithm %s", 1441b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt obuf); 1451b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 1461b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 1471b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 1481b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* 1491b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * RFC 2898, C. 1501b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * 1511b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * PBKDF2-params ::= SEQUENCE { 1521b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * salt CHOICE { 1531b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * specified OCTET STRING, 1541b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}} 1551b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * }, 1561b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * iterationCount INTEGER (1..MAX), 1571b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * keyLength INTEGER (1..MAX) OPTIONAL, 1581b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT 1591b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * algid-hmacWithSHA1 1601b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * } 1611b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt */ 1621b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 1631b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 1641b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 1651b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 1661b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 1671b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #5: Expected SEQUENCE (PBKDF2-params) - found class %d tag 0x%x", 1681b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 1691b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 1701b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 1711b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 1721b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = hdr.payload; 1731b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt end = hdr.payload + hdr.length; 1741b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 1751b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* For now, only support the salt CHOICE specified (OCTET STRING) */ 1761b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 1771b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 1781b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != ASN1_TAG_OCTETSTRING || 1791b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.length > sizeof(params->salt)) { 1801b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 1811b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #5: Expected OCTET STRING (salt.specified) - found class %d tag 0x%x size %d", 1821b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag, hdr.length); 1831b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 1841b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 1851b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = hdr.payload + hdr.length; 1861b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt os_memcpy(params->salt, hdr.payload, hdr.length); 1871b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt params->salt_len = hdr.length; 1881b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_hexdump(MSG_DEBUG, "PKCS #5: salt", params->salt, params->salt_len); 1891b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 1901b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* iterationCount INTEGER */ 1911b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 1921b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { 1931b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 1941b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #5: Expected INTEGER - found class %d tag 0x%x", 1951b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 1961b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 1971b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 1981b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (hdr.length == 1) { 1991b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt params->iter_count = *hdr.payload; 2001b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } else if (hdr.length == 2) { 2011b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt params->iter_count = WPA_GET_BE16(hdr.payload); 2021b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } else if (hdr.length == 4) { 2031b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt params->iter_count = WPA_GET_BE32(hdr.payload); 2041b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } else { 2051b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_hexdump(MSG_DEBUG, 2061b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #5: Unsupported INTEGER value (iterationCount)", 2071b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.payload, hdr.length); 2081b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 2091b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 2101b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #5: iterationCount=0x%x", 2111b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt params->iter_count); 2121b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (params->iter_count == 0 || params->iter_count > 0xffff) { 2131b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_INFO, "PKCS #5: Unsupported iterationCount=0x%x", 2141b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt params->iter_count); 2151b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 2161b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 2171b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 2181b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* For now, ignore optional keyLength and prf */ 2191b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 2201b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = kdf_end; 2211b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 2221b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} */ 2231b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 2241b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, enc_alg_end - pos, &hdr) < 0 || 2251b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 2261b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 2271b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 2281b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #5: Expected SEQUENCE (encryptionScheme) - found class %d tag 0x%x", 2291b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag); 2301b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 2311b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 2321b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 2331b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = hdr.payload; 2341b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt end = hdr.payload + hdr.length; 2351b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 2361b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_oid(pos, end - pos, &oid, &pos)) { 2371b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 2381b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #5: Failed to parse OID (encryptionScheme algorithm)"); 2391b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 2401b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 2411b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 2421b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt asn1_oid_to_str(&oid, obuf, sizeof(obuf)); 2431b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #5: PBES2 encryptionScheme algorithm %s", 2441b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt obuf); 2451b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (enc_alg_is_oid(&oid, 7)) { 2461b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt params->enc_alg = PBES2_ENC_ALG_DES_EDE3_CBC; 2471b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } else { 2481b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 2491b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #5: Unsupported PBES2 encryptionScheme algorithm %s", 2501b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt obuf); 2511b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 2521b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 2531b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 2541b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* 2551b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * RFC 2898, B.2.2: 2561b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * The parameters field associated with this OID in an 2571b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * AlgorithmIdentifier shall have type OCTET STRING (SIZE(8)), 2581b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * specifying the initialization vector for CBC mode. 2591b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt */ 2601b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 2611b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 2621b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.tag != ASN1_TAG_OCTETSTRING || 2631b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.length != 8) { 2641b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, 2651b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt "PKCS #5: Expected OCTET STRING (SIZE(8)) (IV) - found class %d tag 0x%x size %d", 2661b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.class, hdr.tag, hdr.length); 2671b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return -1; 2681b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 2691b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt os_memcpy(params->iv, hdr.payload, hdr.length); 2701b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt params->iv_len = hdr.length; 2711b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_hexdump(MSG_DEBUG, "PKCS #5: IV", params->iv, params->iv_len); 2721b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 2731b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return 0; 2741b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 2751b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 2761b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int pkcs5_get_params(const u8 *enc_alg, size_t enc_alg_len, 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct pkcs5_params *params) 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *enc_alg_end, *pos, *end; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_oid oid; 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char obuf[80]; 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* AlgorithmIdentifier */ 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enc_alg_end = enc_alg + enc_alg_len; 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(params, 0, sizeof(*params)); 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_oid(enc_alg, enc_alg_end - enc_alg, &oid, &pos)) { 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #5: Failed to parse OID " 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(algorithm)"); 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt asn1_oid_to_str(&oid, obuf, sizeof(obuf)); 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #5: encryption algorithm %s", obuf); 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->alg = pkcs5_get_alg(&oid); 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->alg == PKCS5_ALG_UNKNOWN) { 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "PKCS #5: unsupported encryption " 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "algorithm %s", obuf); 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3061b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (params->alg == PKCS5_ALG_PBES2) 3071b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return pkcs5_get_params_pbes2(params, pos, enc_alg_end); 3081b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 3091b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* PBES1 */ 3101b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PKCS#5, Section 8 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PBEParameter ::= SEQUENCE { 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * salt OCTET STRING SIZE(8), 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * iterationCount INTEGER } 3161b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * 3171b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * Note: The same implementation can be used to parse the PKCS #12 3181b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * version described in RFC 7292, C: 3191b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * pkcs-12PbeParams ::= SEQUENCE { 3201b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * salt OCTET STRING, 3211b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * iterations INTEGER 3221b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * } 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, enc_alg_end - pos, &hdr) < 0 || 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #5: Expected SEQUENCE " 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(PBEParameter) - found class %d tag 0x%x", 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = hdr.payload + hdr.length; 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3361b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* salt OCTET STRING SIZE(8) (PKCS #5) or OCTET STRING (PKCS #12) */ 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_OCTETSTRING || 3401b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt hdr.length > sizeof(params->salt)) { 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #5: Expected OCTETSTRING SIZE(8) " 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(salt) - found class %d tag 0x%x size %d", 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag, hdr.length); 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload + hdr.length; 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(params->salt, hdr.payload, hdr.length); 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->salt_len = hdr.length; 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "PKCS #5: salt", 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->salt, params->salt_len); 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* iterationCount INTEGER */ 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #5: Expected INTEGER - found " 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "class %d tag 0x%x", hdr.class, hdr.tag); 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.length == 1) 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->iter_count = *hdr.payload; 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (hdr.length == 2) 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->iter_count = WPA_GET_BE16(hdr.payload); 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (hdr.length == 4) 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->iter_count = WPA_GET_BE32(hdr.payload); 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "PKCS #5: Unsupported INTEGER value " 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " (iterationCount)", 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.payload, hdr.length); 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #5: iterationCount=0x%x", 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->iter_count); 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->iter_count == 0 || params->iter_count > 0xffff) { 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "PKCS #5: Unsupported " 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "iterationCount=0x%x", params->iter_count); 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3831b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic struct crypto_cipher * 3841b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtpkcs5_crypto_init_pbes2(struct pkcs5_params *params, const char *passwd) 3851b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 3861b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt u8 key[24]; 3871b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 3881b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (params->enc_alg != PBES2_ENC_ALG_DES_EDE3_CBC || 3891b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt params->iv_len != 8) 3901b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return NULL; 3911b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 3921b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_hexdump_ascii_key(MSG_DEBUG, "PKCS #5: PBES2 password for PBKDF2", 3931b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt passwd, os_strlen(passwd)); 3941b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_hexdump(MSG_DEBUG, "PKCS #5: PBES2 salt for PBKDF2", 3951b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt params->salt, params->salt_len); 3961b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #5: PBES2 PBKDF2 iterations: %u", 3971b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt params->iter_count); 3981b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (pbkdf2_sha1(passwd, params->salt, params->salt_len, 3991b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt params->iter_count, key, sizeof(key)) < 0) 4001b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return NULL; 4011b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "PKCS #5: DES EDE3 key", key, sizeof(key)); 4021b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_hexdump(MSG_DEBUG, "PKCS #5: DES IV", params->iv, params->iv_len); 4031b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4041b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return crypto_cipher_init(CRYPTO_CIPHER_ALG_3DES, params->iv, 4051b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt key, sizeof(key)); 4061b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 4071b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4081b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4091b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic void add_byte_array_mod(u8 *a, const u8 *b, size_t len) 4101b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 4111b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt size_t i; 4121b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt unsigned int carry = 0; 4131b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4141b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt for (i = len - 1; i < len; i--) { 4151b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt carry = carry + a[i] + b[i]; 4161b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt a[i] = carry & 0xff; 4171b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt carry >>= 8; 4181b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 4191b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 4201b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4211b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4221b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int pkcs12_key_gen(const u8 *pw, size_t pw_len, const u8 *salt, 4231b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt size_t salt_len, u8 id, unsigned int iter, 4241b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt size_t out_len, u8 *out) 4251b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 4261b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt unsigned int u, v, S_len, P_len, i; 4271b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt u8 *D = NULL, *I = NULL, *B = NULL, *pos; 4281b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt int res = -1; 4291b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4301b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* RFC 7292, B.2 */ 4311b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt u = SHA1_MAC_LEN; 4321b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt v = 64; 4331b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4341b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* D = copies of ID */ 4351b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt D = os_malloc(v); 4361b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (!D) 4371b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt goto done; 4381b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt os_memset(D, id, v); 4391b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4401b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* S = copies of salt; P = copies of password, I = S || P */ 4411b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt S_len = v * ((salt_len + v - 1) / v); 4421b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt P_len = v * ((pw_len + v - 1) / v); 4431b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt I = os_malloc(S_len + P_len); 4441b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (!I) 4451b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt goto done; 4461b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pos = I; 4471b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (salt_len) { 4481b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt for (i = 0; i < S_len; i++) 4491b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt *pos++ = salt[i % salt_len]; 4501b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 4511b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (pw_len) { 4521b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt for (i = 0; i < P_len; i++) 4531b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt *pos++ = pw[i % pw_len]; 4541b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 4551b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4561b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt B = os_malloc(v); 4571b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (!B) 4581b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt goto done; 4591b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4601b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt for (;;) { 4611b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt u8 hash[SHA1_MAC_LEN]; 4621b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt const u8 *addr[2]; 4631b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt size_t len[2]; 4641b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4651b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt addr[0] = D; 4661b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt len[0] = v; 4671b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt addr[1] = I; 4681b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt len[1] = S_len + P_len; 4691b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (sha1_vector(2, addr, len, hash) < 0) 4701b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt goto done; 4711b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4721b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt addr[0] = hash; 4731b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt len[0] = SHA1_MAC_LEN; 4741b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt for (i = 1; i < iter; i++) { 4751b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (sha1_vector(1, addr, len, hash) < 0) 4761b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt goto done; 4771b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 4781b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4791b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (out_len <= u) { 4801b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt os_memcpy(out, hash, out_len); 4811b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt res = 0; 4821b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt goto done; 4831b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 4841b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4851b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt os_memcpy(out, hash, u); 4861b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt out += u; 4871b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt out_len -= u; 4881b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4891b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* I_j = (I_j + B + 1) mod 2^(v*8) */ 4901b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt /* B = copies of Ai (final hash value) */ 4911b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt for (i = 0; i < v; i++) 4921b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt B[i] = hash[i % u]; 4931b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt inc_byte_array(B, v); 4941b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt for (i = 0; i < S_len + P_len; i += v) 4951b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt add_byte_array_mod(&I[i], B, v); 4961b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 4971b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 4981b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtdone: 4991b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt os_free(B); 5001b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt os_free(I); 5011b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt os_free(D); 5021b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return res; 5031b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 5041b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5051b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5061b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt#define PKCS12_ID_ENC 1 5071b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt#define PKCS12_ID_IV 2 5081b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt#define PKCS12_ID_MAC 3 5091b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5101b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic struct crypto_cipher * 5111b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtpkcs12_crypto_init_sha1(struct pkcs5_params *params, const char *passwd) 5121b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{ 5131b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt unsigned int i; 5141b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt u8 *pw; 5151b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt size_t pw_len; 5161b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt u8 key[24]; 5171b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt u8 iv[8]; 5181b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5191b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (params->alg != PKCS5_ALG_SHA1_3DES_CBC) 5201b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return NULL; 5211b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5221b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pw_len = passwd ? os_strlen(passwd) : 0; 5231b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pw = os_malloc(2 * (pw_len + 1)); 5241b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (!pw) 5251b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return NULL; 5261b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (pw_len) { 5271b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt for (i = 0; i <= pw_len; i++) 5281b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt WPA_PUT_BE16(&pw[2 * i], passwd[i]); 5291b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pw_len = 2 * (pw_len + 1); 5301b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 5311b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5321b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (pkcs12_key_gen(pw, pw_len, params->salt, params->salt_len, 5331b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt PKCS12_ID_ENC, params->iter_count, 5341b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt sizeof(key), key) < 0 || 5351b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt pkcs12_key_gen(pw, pw_len, params->salt, params->salt_len, 5361b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt PKCS12_ID_IV, params->iter_count, 5371b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt sizeof(iv), iv) < 0) { 5381b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt os_free(pw); 5391b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return NULL; 5401b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt } 5411b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5421b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt os_free(pw); 5431b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5441b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "PKCS #12: DES key", key, sizeof(key)); 5451b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "PKCS #12: DES IV", iv, sizeof(iv)); 5461b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5471b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return crypto_cipher_init(CRYPTO_CIPHER_ALG_3DES, iv, key, sizeof(key)); 5481b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt} 5491b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5501b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct crypto_cipher * pkcs5_crypto_init(struct pkcs5_params *params, 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *passwd) 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int i; 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[MD5_MAC_LEN]; 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[2]; 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[2]; 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5591b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (params->alg == PKCS5_ALG_PBES2) 5601b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return pkcs5_crypto_init_pbes2(params, passwd); 5611b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5621b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt if (params->alg == PKCS5_ALG_SHA1_3DES_CBC) 5631b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt return pkcs12_crypto_init_sha1(params, passwd); 5641b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->alg != PKCS5_ALG_MD5_DES_CBC) 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = (const u8 *) passwd; 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = os_strlen(passwd); 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = params->salt; 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = params->salt_len; 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (md5_vector(2, addr, len, hash) < 0) 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = hash; 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = MD5_MAC_LEN; 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 1; i < params->iter_count; i++) { 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (md5_vector(1, addr, len, hash) < 0) 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: DES key parity bits(?) */ 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "PKCS #5: DES key", hash, 8); 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "PKCS #5: DES IV", hash + 8, 8); 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return crypto_cipher_init(CRYPTO_CIPHER_ALG_DES, hash + 8, hash, 8); 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu8 * pkcs5_decrypt(const u8 *enc_alg, size_t enc_alg_len, 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *enc_data, size_t enc_data_len, 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *passwd, size_t *data_len) 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct crypto_cipher *ctx; 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *eb, pad; 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct pkcs5_params params; 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int i; 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pkcs5_get_params(enc_alg, enc_alg_len, ¶ms) < 0) { 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #5: Unsupported parameters"); 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx = pkcs5_crypto_init(¶ms, passwd); 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ctx == NULL) { 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #5: Failed to initialize crypto"); 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* PKCS #5, Section 7 - Decryption process */ 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (enc_data_len < 16 || enc_data_len % 8) { 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "PKCS #5: invalid length of ciphertext " 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%d", (int) enc_data_len); 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_cipher_deinit(ctx); 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eb = os_malloc(enc_data_len); 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eb == NULL) { 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_cipher_deinit(ctx); 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (crypto_cipher_decrypt(ctx, enc_data, eb, enc_data_len) < 0) { 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "PKCS #5: Failed to decrypt EB"); 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_cipher_deinit(ctx); 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(eb); 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_cipher_deinit(ctx); 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad = eb[enc_data_len - 1]; 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pad > 8) { 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "PKCS #5: Invalid PS octet 0x%x", pad); 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(eb); 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = enc_data_len - pad; i < enc_data_len; i++) { 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eb[i] != pad) { 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_INFO, "PKCS #5: Invalid PS", 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eb + enc_data_len - pad, pad); 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(eb); 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "PKCS #5: message M (encrypted key)", 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eb, enc_data_len - pad); 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *data_len = enc_data_len - pad; 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eb; 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 651