pin_internal.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "device/fido/pin_internal.h"
  5. #include <string>
  6. #include <utility>
  7. #include "base/i18n/char_iterator.h"
  8. #include "base/no_destructor.h"
  9. #include "base/strings/string_util.h"
  10. #include "crypto/random.h"
  11. #include "third_party/boringssl/src/include/openssl/aes.h"
  12. #include "third_party/boringssl/src/include/openssl/bn.h"
  13. #include "third_party/boringssl/src/include/openssl/ec.h"
  14. #include "third_party/boringssl/src/include/openssl/ec_key.h"
  15. #include "third_party/boringssl/src/include/openssl/ecdh.h"
  16. #include "third_party/boringssl/src/include/openssl/evp.h"
  17. #include "third_party/boringssl/src/include/openssl/hkdf.h"
  18. #include "third_party/boringssl/src/include/openssl/hmac.h"
  19. #include "third_party/boringssl/src/include/openssl/mem.h"
  20. #include "third_party/boringssl/src/include/openssl/sha.h"
  21. namespace device {
  22. namespace pin {
  23. absl::optional<bssl::UniquePtr<EC_POINT>> PointFromKeyAgreementResponse(
  24. const EC_GROUP* group,
  25. const KeyAgreementResponse& response) {
  26. bssl::UniquePtr<EC_POINT> ret(EC_POINT_new(group));
  27. bssl::UniquePtr<BIGNUM> x_bn(BN_new()), y_bn(BN_new());
  28. BN_bin2bn(response.x, sizeof(response.x), x_bn.get());
  29. BN_bin2bn(response.y, sizeof(response.y), y_bn.get());
  30. const bool on_curve =
  31. EC_POINT_set_affine_coordinates_GFp(group, ret.get(), x_bn.get(),
  32. y_bn.get(), nullptr /* ctx */) == 1;
  33. if (!on_curve) {
  34. return absl::nullopt;
  35. }
  36. return ret;
  37. }
  38. // ProtocolV1 implements CTAP2.1 PIN/UV Auth Protocol One (6.5.10).
  39. class ProtocolV1 : public Protocol {
  40. private:
  41. static constexpr size_t kSharedKeySize = 32u;
  42. static constexpr size_t kSignatureSize = 16u;
  43. std::array<uint8_t, kP256X962Length> Encapsulate(
  44. const KeyAgreementResponse& peers_key,
  45. std::vector<uint8_t>* out_shared_key) const override {
  46. bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
  47. CHECK(EC_KEY_generate_key(key.get()));
  48. absl::optional<bssl::UniquePtr<EC_POINT>> peers_point =
  49. PointFromKeyAgreementResponse(EC_KEY_get0_group(key.get()), peers_key);
  50. *out_shared_key = CalculateSharedKey(key.get(), peers_point->get());
  51. // KeyAgreementResponse parsing ensures that the point is on the curve.
  52. DCHECK(peers_point);
  53. std::array<uint8_t, kP256X962Length> x962;
  54. CHECK_EQ(x962.size(),
  55. EC_POINT_point2oct(EC_KEY_get0_group(key.get()),
  56. EC_KEY_get0_public_key(key.get()),
  57. POINT_CONVERSION_UNCOMPRESSED, x962.data(),
  58. x962.size(), nullptr /* BN_CTX */));
  59. return x962;
  60. }
  61. std::vector<uint8_t> Encrypt(
  62. base::span<const uint8_t> shared_key,
  63. base::span<const uint8_t> plaintext) const override {
  64. DCHECK_EQ(plaintext.size() % AES_BLOCK_SIZE, 0u);
  65. DCHECK_EQ(shared_key.size(), kSharedKeySize);
  66. std::vector<uint8_t> ciphertext(plaintext.size());
  67. EVP_CIPHER_CTX aes_ctx;
  68. EVP_CIPHER_CTX_init(&aes_ctx);
  69. const uint8_t kZeroIV[AES_BLOCK_SIZE] = {};
  70. CHECK(EVP_EncryptInit_ex(&aes_ctx, EVP_aes_256_cbc(), nullptr,
  71. shared_key.data(), kZeroIV));
  72. CHECK(EVP_CIPHER_CTX_set_padding(&aes_ctx, 0 /* no padding */));
  73. CHECK(EVP_Cipher(&aes_ctx, ciphertext.data(), plaintext.data(),
  74. plaintext.size()));
  75. EVP_CIPHER_CTX_cleanup(&aes_ctx);
  76. return ciphertext;
  77. }
  78. std::vector<uint8_t> Decrypt(
  79. base::span<const uint8_t> shared_key,
  80. base::span<const uint8_t> ciphertext) const override {
  81. DCHECK_EQ(ciphertext.size() % AES_BLOCK_SIZE, 0u);
  82. DCHECK_EQ(shared_key.size(), kSharedKeySize);
  83. std::vector<uint8_t> plaintext(ciphertext.size());
  84. EVP_CIPHER_CTX aes_ctx;
  85. EVP_CIPHER_CTX_init(&aes_ctx);
  86. const uint8_t kZeroIV[AES_BLOCK_SIZE] = {};
  87. CHECK(EVP_DecryptInit_ex(&aes_ctx, EVP_aes_256_cbc(), nullptr,
  88. shared_key.data(), kZeroIV));
  89. CHECK(EVP_CIPHER_CTX_set_padding(&aes_ctx, 0 /* no padding */));
  90. CHECK(EVP_Cipher(&aes_ctx, plaintext.data(), ciphertext.data(),
  91. ciphertext.size()));
  92. EVP_CIPHER_CTX_cleanup(&aes_ctx);
  93. return plaintext;
  94. }
  95. std::vector<uint8_t> Authenticate(
  96. base::span<const uint8_t> key,
  97. base::span<const uint8_t> data) const override {
  98. // Authenticate can be invoked with the shared secret or with a PIN/UV Auth
  99. // Token. In CTAP2.1, V1 tokens are fixed at 16 or 32 bytes. But in CTAP2.0
  100. // they may be any multiple of 16 bytes. We don't know the CTAP version, so
  101. // only enforce the latter.
  102. static_assert(kSharedKeySize == 32u, "");
  103. DCHECK_EQ(key.size() % AES_BLOCK_SIZE, 0u);
  104. std::vector<uint8_t> pin_auth(SHA256_DIGEST_LENGTH);
  105. unsigned hmac_bytes;
  106. CHECK(HMAC(EVP_sha256(), key.data(), key.size(), data.data(), data.size(),
  107. pin_auth.data(), &hmac_bytes));
  108. DCHECK_EQ(pin_auth.size(), static_cast<size_t>(hmac_bytes));
  109. pin_auth.resize(kSignatureSize);
  110. return pin_auth;
  111. }
  112. bool Verify(base::span<const uint8_t> key,
  113. base::span<const uint8_t> data,
  114. base::span<const uint8_t> signature) const override {
  115. if (signature.size() != kSignatureSize) {
  116. return false;
  117. }
  118. const std::vector<uint8_t> computed_signature = Authenticate(key, data);
  119. CHECK_EQ(computed_signature.size(), kSignatureSize);
  120. return CRYPTO_memcmp(signature.data(), computed_signature.data(),
  121. kSignatureSize) == 0;
  122. }
  123. std::vector<uint8_t> CalculateSharedKey(
  124. const EC_KEY* key,
  125. const EC_POINT* peers_key) const override {
  126. std::vector<uint8_t> shared_key(SHA256_DIGEST_LENGTH);
  127. CHECK_EQ(static_cast<int>(SHA256_DIGEST_LENGTH),
  128. ECDH_compute_key(shared_key.data(), shared_key.size(), peers_key,
  129. key, SHA256KDF));
  130. return shared_key;
  131. }
  132. static void* SHA256KDF(const void* in,
  133. size_t in_len,
  134. void* out,
  135. size_t* out_len) {
  136. DCHECK_GE(*out_len, static_cast<size_t>(SHA256_DIGEST_LENGTH));
  137. SHA256(reinterpret_cast<const uint8_t*>(in), in_len,
  138. reinterpret_cast<uint8_t*>(out));
  139. *out_len = SHA256_DIGEST_LENGTH;
  140. return out;
  141. }
  142. };
  143. // ProtocolV2 implements CTAP2.1 PIN/UV Auth Protocol Two (6.5.11).
  144. class ProtocolV2 : public ProtocolV1 {
  145. private:
  146. static constexpr size_t kAESKeyLength = 32;
  147. static constexpr size_t kHMACKeyLength = 32;
  148. static constexpr size_t kSharedKeyLength = kAESKeyLength + kHMACKeyLength;
  149. static constexpr size_t kPINUVAuthTokenLength = 32;
  150. static constexpr size_t kSignatureSize = SHA256_DIGEST_LENGTH;
  151. // GetHMACSubKey returns the HMAC-key portion of the shared secret.
  152. static base::span<const uint8_t, kHMACKeyLength> GetHMACSubKey(
  153. base::span<const uint8_t, kSharedKeyLength> shared_key) {
  154. CHECK_EQ(shared_key.size(), kSharedKeyLength);
  155. return base::make_span<kHMACKeyLength>(
  156. shared_key.subspan(0, kHMACKeyLength));
  157. }
  158. // GetAESSubKey returns the HMAC-key portion of the shared secret.
  159. static base::span<const uint8_t, kAESKeyLength> GetAESSubKey(
  160. base::span<const uint8_t, kSharedKeyLength> shared_key) {
  161. return base::make_span<kAESKeyLength>(shared_key.subspan(kHMACKeyLength));
  162. }
  163. std::vector<uint8_t> Encrypt(
  164. base::span<const uint8_t> shared_key,
  165. base::span<const uint8_t> plaintext) const override {
  166. DCHECK_EQ(plaintext.size() % AES_BLOCK_SIZE, 0u);
  167. const base::span<const uint8_t, kAESKeyLength> aes_key =
  168. GetAESSubKey(base::make_span<kSharedKeyLength>(shared_key));
  169. std::vector<uint8_t> result(AES_BLOCK_SIZE + plaintext.size());
  170. const base::span<uint8_t> iv =
  171. base::make_span(result).subspan(0, AES_BLOCK_SIZE);
  172. const base::span<uint8_t> ciphertext =
  173. base::make_span(result).subspan(AES_BLOCK_SIZE);
  174. crypto::RandBytes(iv);
  175. EVP_CIPHER_CTX aes_ctx;
  176. EVP_CIPHER_CTX_init(&aes_ctx);
  177. CHECK(EVP_EncryptInit_ex(&aes_ctx, EVP_aes_256_cbc(), nullptr,
  178. aes_key.data(), iv.data()));
  179. CHECK(EVP_CIPHER_CTX_set_padding(&aes_ctx, 0 /* no padding */));
  180. CHECK(EVP_Cipher(&aes_ctx, ciphertext.data(), plaintext.data(),
  181. plaintext.size()));
  182. EVP_CIPHER_CTX_cleanup(&aes_ctx);
  183. return result;
  184. }
  185. std::vector<uint8_t> Decrypt(base::span<const uint8_t> shared_key,
  186. base::span<const uint8_t> input) const override {
  187. DCHECK_EQ(input.size() % AES_BLOCK_SIZE, 0u);
  188. const base::span<const uint8_t, kAESKeyLength> aes_key =
  189. GetAESSubKey(base::make_span<kSharedKeyLength>(shared_key));
  190. const base::span<const uint8_t> iv = input.subspan(0, AES_BLOCK_SIZE);
  191. const base::span<const uint8_t> ciphertext = input.subspan(AES_BLOCK_SIZE);
  192. std::vector<uint8_t> plaintext(ciphertext.size());
  193. EVP_CIPHER_CTX aes_ctx;
  194. EVP_CIPHER_CTX_init(&aes_ctx);
  195. CHECK(EVP_DecryptInit_ex(&aes_ctx, EVP_aes_256_cbc(), nullptr,
  196. aes_key.data(), iv.data()));
  197. CHECK(EVP_CIPHER_CTX_set_padding(&aes_ctx, 0 /* no padding */));
  198. CHECK(EVP_Cipher(&aes_ctx, plaintext.data(), ciphertext.data(),
  199. ciphertext.size()));
  200. EVP_CIPHER_CTX_cleanup(&aes_ctx);
  201. return plaintext;
  202. }
  203. std::vector<uint8_t> Authenticate(
  204. base::span<const uint8_t> key,
  205. base::span<const uint8_t> data) const override {
  206. // Authenticate can be invoked with the shared secret or with a PIN/UV Auth
  207. // Token, which is fixed at 32 bytes in V2.
  208. DCHECK(key.size() == kSharedKeyLength ||
  209. key.size() == kPINUVAuthTokenLength);
  210. const base::span<const uint8_t, kHMACKeyLength> hmac_key =
  211. (key.size() == kSharedKeyLength
  212. ? GetHMACSubKey(base::make_span<kSharedKeyLength>(key))
  213. : base::make_span<kPINUVAuthTokenLength>(key));
  214. std::vector<uint8_t> pin_auth(SHA256_DIGEST_LENGTH);
  215. unsigned hmac_bytes;
  216. CHECK(HMAC(EVP_sha256(), hmac_key.data(), hmac_key.size(), data.data(),
  217. data.size(), pin_auth.data(), &hmac_bytes));
  218. DCHECK_EQ(pin_auth.size(), static_cast<size_t>(hmac_bytes));
  219. return pin_auth;
  220. }
  221. bool Verify(base::span<const uint8_t> key,
  222. base::span<const uint8_t> data,
  223. base::span<const uint8_t> signature) const override {
  224. if (signature.size() != kSignatureSize) {
  225. return false;
  226. }
  227. const std::vector<uint8_t> computed_signature = Authenticate(key, data);
  228. CHECK_EQ(computed_signature.size(), kSignatureSize);
  229. return CRYPTO_memcmp(signature.data(), computed_signature.data(),
  230. kSignatureSize) == 0;
  231. }
  232. std::vector<uint8_t> CalculateSharedKey(
  233. const EC_KEY* key,
  234. const EC_POINT* peers_key) const override {
  235. std::vector<uint8_t> shared_key(kSharedKeyLength);
  236. CHECK_EQ(static_cast<int>(kSharedKeyLength),
  237. ECDH_compute_key(shared_key.data(), shared_key.size(), peers_key,
  238. key, KDF));
  239. return shared_key;
  240. }
  241. static void* KDF(const void* in, size_t in_len, void* out, size_t* out_len) {
  242. static_assert(kSharedKeyLength == 2 * SHA256_DIGEST_LENGTH, "");
  243. DCHECK_GE(*out_len, static_cast<size_t>(kSharedKeyLength));
  244. auto hmac_key_out =
  245. base::make_span(reinterpret_cast<uint8_t*>(out), SHA256_DIGEST_LENGTH);
  246. auto aes_key_out =
  247. base::make_span(reinterpret_cast<uint8_t*>(out) + SHA256_DIGEST_LENGTH,
  248. SHA256_DIGEST_LENGTH);
  249. constexpr uint8_t kHMACKeyInfo[] = "CTAP2 HMAC key";
  250. constexpr uint8_t kAESKeyInfo[] = "CTAP2 AES key";
  251. constexpr uint8_t kZeroSalt[32] = {};
  252. CHECK(HKDF(hmac_key_out.data(), hmac_key_out.size(), EVP_sha256(),
  253. reinterpret_cast<const uint8_t*>(in), in_len, kZeroSalt,
  254. sizeof(kZeroSalt), kHMACKeyInfo, sizeof(kHMACKeyInfo) - 1));
  255. CHECK(HKDF(aes_key_out.data(), aes_key_out.size(), EVP_sha256(),
  256. reinterpret_cast<const uint8_t*>(in), in_len, kZeroSalt,
  257. sizeof(kZeroSalt), kAESKeyInfo, sizeof(kAESKeyInfo) - 1));
  258. *out_len = kSharedKeyLength;
  259. return out;
  260. }
  261. };
  262. // static
  263. const Protocol& ProtocolVersion(PINUVAuthProtocol protocol) {
  264. static const base::NoDestructor<ProtocolV1> kProtocolV1;
  265. static const base::NoDestructor<ProtocolV2> kProtocolV2;
  266. switch (protocol) {
  267. case PINUVAuthProtocol::kV1:
  268. return *kProtocolV1;
  269. case PINUVAuthProtocol::kV2:
  270. return *kProtocolV2;
  271. }
  272. }
  273. } // namespace pin
  274. } // namespace device