ecdsa.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. // Copyright 2016 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. #ifndef COMPONENTS_CLIENT_UPDATE_PROTOCOL_ECDSA_H_
  5. #define COMPONENTS_CLIENT_UPDATE_PROTOCOL_ECDSA_H_
  6. #include <stdint.h>
  7. #include <memory>
  8. #include <string>
  9. #include <vector>
  10. #include "base/strings/string_piece.h"
  11. namespace client_update_protocol {
  12. // Client Update Protocol v2, or CUP-ECDSA, is used by Google Update (Omaha)
  13. // servers to ensure freshness and authenticity of server responses over HTTP,
  14. // without the overhead of HTTPS -- namely, no PKI, no guarantee of privacy, and
  15. // no request replay protection.
  16. //
  17. // CUP-ECDSA relies on a single signing operation using ECDSA with SHA-256,
  18. // instead of the original CUP which used HMAC-SHA1 with a random signing key
  19. // encrypted using RSA.
  20. //
  21. // Each |Ecdsa| object represents a single network ping in flight -- a call to
  22. // SignRequest() generates internal state that will be used by
  23. // ValidateResponse().
  24. class Ecdsa {
  25. public:
  26. Ecdsa() = delete;
  27. Ecdsa(const Ecdsa&) = delete;
  28. Ecdsa& operator=(const Ecdsa&) = delete;
  29. ~Ecdsa();
  30. struct RequestParameters {
  31. std::string query_cup2key;
  32. std::string hash_hex;
  33. };
  34. // Initializes this instance of CUP-ECDSA with a versioned public key.
  35. // |key_version| must be non-negative. |public_key| is expected to be a
  36. // DER-encoded ASN.1 SubjectPublicKeyInfo containing an ECDSA public key.
  37. // Returns a NULL pointer on failure.
  38. static std::unique_ptr<Ecdsa> Create(int key_version,
  39. const base::StringPiece& public_key);
  40. // Generates freshness/authentication data for an outgoing ping.
  41. // |request_body| contains the body of the ping in UTF-8. On return,
  42. // |query_params| contains a set of query parameters (in UTF-8) to be appended
  43. // to the URL.
  44. //
  45. // This method will store internal state in this instance used by calls to
  46. // ValidateResponse(); if you need to have multiple pings in flight,
  47. // initialize a separate CUP-ECDSA instance for each one.
  48. void SignRequest(const base::StringPiece& request_body,
  49. std::string* query_params);
  50. // Generates freshness/authentication data for an outgoing ping.
  51. // |request_body| contains the body of the ping in UTF-8. Returns the
  52. // parameters that must be sent to the server for ECDSA authentication.
  53. //
  54. // This method will store internal state in this instance used by calls to
  55. // ValidateResponse(); if you need to have multiple pings in flight,
  56. // initialize a separate CUP-ECDSA instance for each one.
  57. RequestParameters SignRequest(const base::StringPiece& request_body);
  58. // Validates a response given to a ping previously signed with
  59. // SignRequest(). |response_body| contains the body of the response in
  60. // UTF-8. |signature| contains the ECDSA signature and observed request
  61. // hash. Returns true if the response is valid and the observed request hash
  62. // matches the sent hash. This method uses internal state that is set by a
  63. // prior SignRequest() call.
  64. bool ValidateResponse(const base::StringPiece& response_body,
  65. const base::StringPiece& signature);
  66. // Sets the key and nonce that were used to generate a signature that is baked
  67. // into a unit test. Note this function encodes |nonce| in decimal, while
  68. // non-test paths use a base64url-encoded, 256-bit string.
  69. void OverrideNonceForTesting(int key_version, uint32_t nonce);
  70. private:
  71. Ecdsa(int key_version, const base::StringPiece& public_key);
  72. // The server keeps multiple signing keys; a version must be sent so that
  73. // the correct signing key is used to sign the assembled message.
  74. const int pub_key_version_;
  75. // The ECDSA public key to use for verifying response signatures.
  76. const std::vector<uint8_t> public_key_;
  77. // The SHA-256 hash of the XML request. This is modified on each call to
  78. // SignRequest(), and checked by ValidateResponse().
  79. std::vector<uint8_t> request_hash_;
  80. // The query string containing key version and nonce in UTF-8 form. This is
  81. // modified on each call to SignRequest(), and checked by ValidateResponse().
  82. std::string request_query_cup2key_;
  83. };
  84. } // namespace client_update_protocol
  85. #endif // COMPONENTS_CLIENT_UPDATE_PROTOCOL_ECDSA_H_