pkcs1.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * PKCS #1 (RSA Encryption)
  3. * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * Alternatively, this software may be distributed under the terms of BSD
  10. * license.
  11. *
  12. * See README and COPYING for more details.
  13. */
  14. #include "includes.h"
  15. #include "common.h"
  16. #include "rsa.h"
  17. #include "pkcs1.h"
  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. * PKCS #1 v1.5, 8.1:
  26. *
  27. * EB = 00 || BT || PS || 00 || D
  28. * BT = 00 or 01 for private-key operation; 02 for public-key operation
  29. * PS = k-3-||D||; at least eight octets
  30. * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero)
  31. * k = length of modulus in octets (modlen)
  32. */
  33. if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) {
  34. wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer "
  35. "lengths (modlen=%lu outlen=%lu inlen=%lu)",
  36. __func__, (unsigned long) modlen,
  37. (unsigned long) *outlen,
  38. (unsigned long) inlen);
  39. return -1;
  40. }
  41. pos = out;
  42. *pos++ = 0x00;
  43. *pos++ = block_type; /* BT */
  44. ps_len = modlen - inlen - 3;
  45. switch (block_type) {
  46. case 0:
  47. os_memset(pos, 0x00, ps_len);
  48. pos += ps_len;
  49. break;
  50. case 1:
  51. os_memset(pos, 0xff, ps_len);
  52. pos += ps_len;
  53. break;
  54. case 2:
  55. if (os_get_random(pos, ps_len) < 0) {
  56. wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get "
  57. "random data for PS", __func__);
  58. return -1;
  59. }
  60. while (ps_len--) {
  61. if (*pos == 0x00)
  62. *pos = 0x01;
  63. pos++;
  64. }
  65. break;
  66. default:
  67. wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type "
  68. "%d", __func__, block_type);
  69. return -1;
  70. }
  71. *pos++ = 0x00;
  72. os_memcpy(pos, in, inlen); /* D */
  73. return 0;
  74. }
  75. int pkcs1_encrypt(int block_type, struct crypto_rsa_key *key,
  76. int use_private, const u8 *in, size_t inlen,
  77. u8 *out, size_t *outlen)
  78. {
  79. size_t modlen;
  80. modlen = crypto_rsa_get_modulus_len(key);
  81. if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen,
  82. out, outlen) < 0)
  83. return -1;
  84. return crypto_rsa_exptmod(out, modlen, out, outlen, key, use_private);
  85. }
  86. int pkcs1_v15_private_key_decrypt(struct crypto_rsa_key *key,
  87. const u8 *in, size_t inlen,
  88. u8 *out, size_t *outlen)
  89. {
  90. int res;
  91. u8 *pos, *end;
  92. res = crypto_rsa_exptmod(in, inlen, out, outlen, key, 1);
  93. if (res)
  94. return res;
  95. if (*outlen < 2 || out[0] != 0 || out[1] != 2)
  96. return -1;
  97. /* Skip PS (pseudorandom non-zero octets) */
  98. pos = out + 2;
  99. end = out + *outlen;
  100. while (*pos && pos < end)
  101. pos++;
  102. if (pos == end)
  103. return -1;
  104. pos++;
  105. *outlen -= pos - out;
  106. /* Strip PKCS #1 header */
  107. os_memmove(out, pos, *outlen);
  108. return 0;
  109. }
  110. int pkcs1_decrypt_public_key(struct crypto_rsa_key *key,
  111. const u8 *crypt, size_t crypt_len,
  112. u8 *plain, size_t *plain_len)
  113. {
  114. size_t len;
  115. u8 *pos;
  116. len = *plain_len;
  117. if (crypto_rsa_exptmod(crypt, crypt_len, plain, &len, key, 0) < 0)
  118. return -1;
  119. /*
  120. * PKCS #1 v1.5, 8.1:
  121. *
  122. * EB = 00 || BT || PS || 00 || D
  123. * BT = 00 or 01
  124. * PS = k-3-||D|| times (00 if BT=00) or (FF if BT=01)
  125. * k = length of modulus in octets
  126. */
  127. if (len < 3 + 8 + 16 /* min hash len */ ||
  128. plain[0] != 0x00 || (plain[1] != 0x00 && plain[1] != 0x01)) {
  129. wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
  130. "structure");
  131. return -1;
  132. }
  133. pos = plain + 3;
  134. if (plain[1] == 0x00) {
  135. /* BT = 00 */
  136. if (plain[2] != 0x00) {
  137. wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature "
  138. "PS (BT=00)");
  139. return -1;
  140. }
  141. while (pos + 1 < plain + len && *pos == 0x00 && pos[1] == 0x00)
  142. pos++;
  143. } else {
  144. /* BT = 01 */
  145. if (plain[2] != 0xff) {
  146. wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature "
  147. "PS (BT=01)");
  148. return -1;
  149. }
  150. while (pos < plain + len && *pos == 0xff)
  151. pos++;
  152. }
  153. if (pos - plain - 2 < 8) {
  154. /* PKCS #1 v1.5, 8.1: At least eight octets long PS */
  155. wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature "
  156. "padding");
  157. return -1;
  158. }
  159. if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) {
  160. wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
  161. "structure (2)");
  162. return -1;
  163. }
  164. pos++;
  165. len -= pos - plain;
  166. /* Strip PKCS #1 header */
  167. os_memmove(plain, pos, len);
  168. *plain_len = len;
  169. return 0;
  170. }