OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/update_client/client_update_protocol_ecdsa.h" | 5 #include "components/client_update_protocol/ecdsa.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/macros.h" | 8 #include "base/macros.h" |
9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
11 #include "base/strings/string_piece.h" | 11 #include "base/strings/string_piece.h" |
12 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
13 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
14 #include "crypto/random.h" | 14 #include "crypto/random.h" |
15 #include "crypto/sha2.h" | 15 #include "crypto/sha2.h" |
16 #include "crypto/signature_verifier.h" | 16 #include "crypto/signature_verifier.h" |
17 | 17 |
18 namespace update_client { | 18 namespace client_update_protocol { |
19 | 19 |
20 namespace { | 20 namespace { |
21 | 21 |
22 std::vector<uint8_t> SHA256HashStr(const base::StringPiece& str) { | 22 std::vector<uint8_t> SHA256HashStr(const base::StringPiece& str) { |
23 std::vector<uint8_t> result(crypto::kSHA256Length); | 23 std::vector<uint8_t> result(crypto::kSHA256Length); |
24 crypto::SHA256HashString(str, &result.front(), result.size()); | 24 crypto::SHA256HashString(str, &result.front(), result.size()); |
25 return result; | 25 return result; |
26 } | 26 } |
27 | 27 |
28 std::vector<uint8_t> SHA256HashVec(const std::vector<uint8_t>& vec) { | 28 std::vector<uint8_t> SHA256HashVec(const std::vector<uint8_t>& vec) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
77 if (!base::HexStringToBytes(hash_hex.as_string(), request_hash_out)) | 77 if (!base::HexStringToBytes(hash_hex.as_string(), request_hash_out)) |
78 return false; | 78 return false; |
79 if (request_hash_out->size() != crypto::kSHA256Length) | 79 if (request_hash_out->size() != crypto::kSHA256Length) |
80 return false; | 80 return false; |
81 | 81 |
82 return true; | 82 return true; |
83 } | 83 } |
84 | 84 |
85 } // namespace | 85 } // namespace |
86 | 86 |
87 ClientUpdateProtocolEcdsa::ClientUpdateProtocolEcdsa( | 87 Ecdsa::Ecdsa(int key_version, const base::StringPiece& public_key) |
88 int key_version, | |
89 const base::StringPiece& public_key) | |
90 : pub_key_version_(key_version), | 88 : pub_key_version_(key_version), |
91 public_key_(public_key.begin(), public_key.end()) {} | 89 public_key_(public_key.begin(), public_key.end()) {} |
92 | 90 |
93 ClientUpdateProtocolEcdsa::~ClientUpdateProtocolEcdsa() {} | 91 Ecdsa::~Ecdsa() {} |
94 | 92 |
95 scoped_ptr<ClientUpdateProtocolEcdsa> ClientUpdateProtocolEcdsa::Create( | 93 scoped_ptr<Ecdsa> Ecdsa::Create(int key_version, |
96 int key_version, | 94 const base::StringPiece& public_key) { |
97 const base::StringPiece& public_key) { | |
98 DCHECK_GT(key_version, 0); | 95 DCHECK_GT(key_version, 0); |
99 DCHECK(!public_key.empty()); | 96 DCHECK(!public_key.empty()); |
100 | 97 |
101 return make_scoped_ptr( | 98 return make_scoped_ptr(new Ecdsa(key_version, public_key)); |
102 new ClientUpdateProtocolEcdsa(key_version, public_key)); | |
103 } | 99 } |
104 | 100 |
105 void ClientUpdateProtocolEcdsa::SignRequest( | 101 void Ecdsa::SignRequest(const base::StringPiece& request_body, |
106 const base::StringPiece& request_body, | 102 std::string* query_params) { |
107 std::string* query_params) { | |
108 DCHECK(!request_body.empty()); | 103 DCHECK(!request_body.empty()); |
109 DCHECK(query_params); | 104 DCHECK(query_params); |
110 | 105 |
111 // Generate a random nonce to use for freshness, build the cup2key query | 106 // Generate a random nonce to use for freshness, build the cup2key query |
112 // string, and compute the SHA-256 hash of the request body. Set these | 107 // string, and compute the SHA-256 hash of the request body. Set these |
113 // two pieces of data aside to use during ValidateResponse(). | 108 // two pieces of data aside to use during ValidateResponse(). |
114 uint32_t nonce = 0; | 109 uint32_t nonce = 0; |
115 crypto::RandBytes(&nonce, sizeof(nonce)); | 110 crypto::RandBytes(&nonce, sizeof(nonce)); |
116 request_query_cup2key_ = base::StringPrintf("%d:%u", pub_key_version_, nonce); | 111 request_query_cup2key_ = base::StringPrintf("%d:%u", pub_key_version_, nonce); |
117 request_hash_ = SHA256HashStr(request_body); | 112 request_hash_ = SHA256HashStr(request_body); |
118 | 113 |
119 // Return the query string for the user to send with the request. | 114 // Return the query string for the user to send with the request. |
120 std::string request_hash_hex = | 115 std::string request_hash_hex = |
121 base::HexEncode(&request_hash_.front(), request_hash_.size()); | 116 base::HexEncode(&request_hash_.front(), request_hash_.size()); |
122 request_hash_hex = base::ToLowerASCII(request_hash_hex); | 117 request_hash_hex = base::ToLowerASCII(request_hash_hex); |
123 | 118 |
124 *query_params = base::StringPrintf("cup2key=%s&cup2hreq=%s", | 119 *query_params = base::StringPrintf("cup2key=%s&cup2hreq=%s", |
125 request_query_cup2key_.c_str(), | 120 request_query_cup2key_.c_str(), |
126 request_hash_hex.c_str()); | 121 request_hash_hex.c_str()); |
127 } | 122 } |
128 | 123 |
129 bool ClientUpdateProtocolEcdsa::ValidateResponse( | 124 bool Ecdsa::ValidateResponse(const base::StringPiece& response_body, |
130 const base::StringPiece& response_body, | 125 const base::StringPiece& server_etag) { |
131 const base::StringPiece& server_etag) { | |
132 DCHECK(!request_hash_.empty()); | 126 DCHECK(!request_hash_.empty()); |
133 DCHECK(!request_query_cup2key_.empty()); | 127 DCHECK(!request_query_cup2key_.empty()); |
134 | 128 |
135 if (response_body.empty() || server_etag.empty()) | 129 if (response_body.empty() || server_etag.empty()) |
136 return false; | 130 return false; |
137 | 131 |
138 // Break the ETag into its two components (the ECDSA signature, and the | 132 // Break the ETag into its two components (the ECDSA signature, and the |
139 // hash of the request that the server observed) and decode to byte buffers. | 133 // hash of the request that the server observed) and decode to byte buffers. |
140 std::vector<uint8_t> signature; | 134 std::vector<uint8_t> signature; |
141 std::vector<uint8_t> observed_request_hash; | 135 std::vector<uint8_t> observed_request_hash; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 // If the verification fails, that implies one of two outcomes: | 177 // If the verification fails, that implies one of two outcomes: |
184 // * The signature was modified | 178 // * The signature was modified |
185 // * The buffer that the server signed does not match the buffer that the | 179 // * The buffer that the server signed does not match the buffer that the |
186 // client assembled -- implying that either request body or response body | 180 // client assembled -- implying that either request body or response body |
187 // was modified, or a different nonce value was used. | 181 // was modified, or a different nonce value was used. |
188 verifier.VerifyUpdate(&signed_message_hash.front(), | 182 verifier.VerifyUpdate(&signed_message_hash.front(), |
189 static_cast<int>(signed_message_hash.size())); | 183 static_cast<int>(signed_message_hash.size())); |
190 return verifier.VerifyFinal(); | 184 return verifier.VerifyFinal(); |
191 } | 185 } |
192 | 186 |
193 } // namespace update_client | 187 } // namespace client_update_protocol |
OLD | NEW |