pkcs5.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*
  2. * PKCS #5 (Password-based Encryption)
  3. * Copyright (c) 2009, 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. #include "includes.h"
  9. #include "common.h"
  10. #include "crypto/crypto.h"
  11. #include "crypto/md5.h"
  12. #include "asn1.h"
  13. #include "pkcs5.h"
  14. struct pkcs5_params {
  15. enum pkcs5_alg {
  16. PKCS5_ALG_UNKNOWN,
  17. PKCS5_ALG_MD5_DES_CBC
  18. } alg;
  19. u8 salt[8];
  20. size_t salt_len;
  21. unsigned int iter_count;
  22. };
  23. static enum pkcs5_alg pkcs5_get_alg(struct asn1_oid *oid)
  24. {
  25. if (oid->len == 7 &&
  26. oid->oid[0] == 1 /* iso */ &&
  27. oid->oid[1] == 2 /* member-body */ &&
  28. oid->oid[2] == 840 /* us */ &&
  29. oid->oid[3] == 113549 /* rsadsi */ &&
  30. oid->oid[4] == 1 /* pkcs */ &&
  31. oid->oid[5] == 5 /* pkcs-5 */ &&
  32. oid->oid[6] == 3 /* pbeWithMD5AndDES-CBC */)
  33. return PKCS5_ALG_MD5_DES_CBC;
  34. return PKCS5_ALG_UNKNOWN;
  35. }
  36. static int pkcs5_get_params(const u8 *enc_alg, size_t enc_alg_len,
  37. struct pkcs5_params *params)
  38. {
  39. struct asn1_hdr hdr;
  40. const u8 *enc_alg_end, *pos, *end;
  41. struct asn1_oid oid;
  42. char obuf[80];
  43. /* AlgorithmIdentifier */
  44. enc_alg_end = enc_alg + enc_alg_len;
  45. os_memset(params, 0, sizeof(*params));
  46. if (asn1_get_oid(enc_alg, enc_alg_end - enc_alg, &oid, &pos)) {
  47. wpa_printf(MSG_DEBUG, "PKCS #5: Failed to parse OID "
  48. "(algorithm)");
  49. return -1;
  50. }
  51. asn1_oid_to_str(&oid, obuf, sizeof(obuf));
  52. wpa_printf(MSG_DEBUG, "PKCS #5: encryption algorithm %s", obuf);
  53. params->alg = pkcs5_get_alg(&oid);
  54. if (params->alg == PKCS5_ALG_UNKNOWN) {
  55. wpa_printf(MSG_INFO, "PKCS #5: unsupported encryption "
  56. "algorithm %s", obuf);
  57. return -1;
  58. }
  59. /*
  60. * PKCS#5, Section 8
  61. * PBEParameter ::= SEQUENCE {
  62. * salt OCTET STRING SIZE(8),
  63. * iterationCount INTEGER }
  64. */
  65. if (asn1_get_next(pos, enc_alg_end - pos, &hdr) < 0 ||
  66. hdr.class != ASN1_CLASS_UNIVERSAL ||
  67. hdr.tag != ASN1_TAG_SEQUENCE) {
  68. wpa_printf(MSG_DEBUG, "PKCS #5: Expected SEQUENCE "
  69. "(PBEParameter) - found class %d tag 0x%x",
  70. hdr.class, hdr.tag);
  71. return -1;
  72. }
  73. pos = hdr.payload;
  74. end = hdr.payload + hdr.length;
  75. /* salt OCTET STRING SIZE(8) */
  76. if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
  77. hdr.class != ASN1_CLASS_UNIVERSAL ||
  78. hdr.tag != ASN1_TAG_OCTETSTRING ||
  79. hdr.length != 8) {
  80. wpa_printf(MSG_DEBUG, "PKCS #5: Expected OCTETSTRING SIZE(8) "
  81. "(salt) - found class %d tag 0x%x size %d",
  82. hdr.class, hdr.tag, hdr.length);
  83. return -1;
  84. }
  85. pos = hdr.payload + hdr.length;
  86. os_memcpy(params->salt, hdr.payload, hdr.length);
  87. params->salt_len = hdr.length;
  88. wpa_hexdump(MSG_DEBUG, "PKCS #5: salt",
  89. params->salt, params->salt_len);
  90. /* iterationCount INTEGER */
  91. if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
  92. hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
  93. wpa_printf(MSG_DEBUG, "PKCS #5: Expected INTEGER - found "
  94. "class %d tag 0x%x", hdr.class, hdr.tag);
  95. return -1;
  96. }
  97. if (hdr.length == 1)
  98. params->iter_count = *hdr.payload;
  99. else if (hdr.length == 2)
  100. params->iter_count = WPA_GET_BE16(hdr.payload);
  101. else if (hdr.length == 4)
  102. params->iter_count = WPA_GET_BE32(hdr.payload);
  103. else {
  104. wpa_hexdump(MSG_DEBUG, "PKCS #5: Unsupported INTEGER value "
  105. " (iterationCount)",
  106. hdr.payload, hdr.length);
  107. return -1;
  108. }
  109. wpa_printf(MSG_DEBUG, "PKCS #5: iterationCount=0x%x",
  110. params->iter_count);
  111. if (params->iter_count == 0 || params->iter_count > 0xffff) {
  112. wpa_printf(MSG_INFO, "PKCS #5: Unsupported "
  113. "iterationCount=0x%x", params->iter_count);
  114. return -1;
  115. }
  116. return 0;
  117. }
  118. static struct crypto_cipher * pkcs5_crypto_init(struct pkcs5_params *params,
  119. const char *passwd)
  120. {
  121. unsigned int i;
  122. u8 hash[MD5_MAC_LEN];
  123. const u8 *addr[2];
  124. size_t len[2];
  125. if (params->alg != PKCS5_ALG_MD5_DES_CBC)
  126. return NULL;
  127. addr[0] = (const u8 *) passwd;
  128. len[0] = os_strlen(passwd);
  129. addr[1] = params->salt;
  130. len[1] = params->salt_len;
  131. if (md5_vector(2, addr, len, hash) < 0)
  132. return NULL;
  133. addr[0] = hash;
  134. len[0] = MD5_MAC_LEN;
  135. for (i = 1; i < params->iter_count; i++) {
  136. if (md5_vector(1, addr, len, hash) < 0)
  137. return NULL;
  138. }
  139. /* TODO: DES key parity bits(?) */
  140. wpa_hexdump_key(MSG_DEBUG, "PKCS #5: DES key", hash, 8);
  141. wpa_hexdump_key(MSG_DEBUG, "PKCS #5: DES IV", hash + 8, 8);
  142. return crypto_cipher_init(CRYPTO_CIPHER_ALG_DES, hash + 8, hash, 8);
  143. }
  144. u8 * pkcs5_decrypt(const u8 *enc_alg, size_t enc_alg_len,
  145. const u8 *enc_data, size_t enc_data_len,
  146. const char *passwd, size_t *data_len)
  147. {
  148. struct crypto_cipher *ctx;
  149. u8 *eb, pad;
  150. struct pkcs5_params params;
  151. unsigned int i;
  152. if (pkcs5_get_params(enc_alg, enc_alg_len, &params) < 0) {
  153. wpa_printf(MSG_DEBUG, "PKCS #5: Unsupported parameters");
  154. return NULL;
  155. }
  156. ctx = pkcs5_crypto_init(&params, passwd);
  157. if (ctx == NULL) {
  158. wpa_printf(MSG_DEBUG, "PKCS #5: Failed to initialize crypto");
  159. return NULL;
  160. }
  161. /* PKCS #5, Section 7 - Decryption process */
  162. if (enc_data_len < 16 || enc_data_len % 8) {
  163. wpa_printf(MSG_INFO, "PKCS #5: invalid length of ciphertext "
  164. "%d", (int) enc_data_len);
  165. crypto_cipher_deinit(ctx);
  166. return NULL;
  167. }
  168. eb = os_malloc(enc_data_len);
  169. if (eb == NULL) {
  170. crypto_cipher_deinit(ctx);
  171. return NULL;
  172. }
  173. if (crypto_cipher_decrypt(ctx, enc_data, eb, enc_data_len) < 0) {
  174. wpa_printf(MSG_DEBUG, "PKCS #5: Failed to decrypt EB");
  175. crypto_cipher_deinit(ctx);
  176. os_free(eb);
  177. return NULL;
  178. }
  179. crypto_cipher_deinit(ctx);
  180. pad = eb[enc_data_len - 1];
  181. if (pad > 8) {
  182. wpa_printf(MSG_INFO, "PKCS #5: Invalid PS octet 0x%x", pad);
  183. os_free(eb);
  184. return NULL;
  185. }
  186. for (i = enc_data_len - pad; i < enc_data_len; i++) {
  187. if (eb[i] != pad) {
  188. wpa_hexdump(MSG_INFO, "PKCS #5: Invalid PS",
  189. eb + enc_data_len - pad, pad);
  190. os_free(eb);
  191. return NULL;
  192. }
  193. }
  194. wpa_hexdump_key(MSG_MSGDUMP, "PKCS #5: message M (encrypted key)",
  195. eb, enc_data_len - pad);
  196. *data_len = enc_data_len - pad;
  197. return eb;
  198. }