| 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/update_client/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/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 9 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
| 10 #include "base/strings/string_piece.h" | 11 #include "base/strings/string_piece.h" |
| 11 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
| 12 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
| 13 #include "crypto/random.h" | 14 #include "crypto/random.h" |
| 14 #include "crypto/sha2.h" | 15 #include "crypto/sha2.h" |
| 15 #include "crypto/signature_verifier.h" | 16 #include "crypto/signature_verifier.h" |
| 16 | 17 |
| 18 namespace update_client { |
| 19 |
| 17 namespace { | 20 namespace { |
| 18 | 21 |
| 19 // This is the algorithm ID for ECDSA with SHA-256. Parameters are ABSENT. | 22 // This is the algorithm ID for ECDSA with SHA-256. Parameters are ABSENT. |
| 20 // RFC 5758: | 23 // RFC 5758: |
| 21 // ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) | 24 // ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) |
| 22 // us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 } | 25 // us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 } |
| 23 // ... | 26 // ... |
| 24 // When the ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with-SHA384, or | 27 // When the ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with-SHA384, or |
| 25 // ecdsa-with-SHA512 algorithm identifier appears in the algorithm field | 28 // ecdsa-with-SHA512 algorithm identifier appears in the algorithm field |
| 26 // as an AlgorithmIdentifier, the encoding MUST omit the parameters | 29 // as an AlgorithmIdentifier, the encoding MUST omit the parameters |
| (...skipping 12 matching lines...) Expand all Loading... |
| 39 } | 42 } |
| 40 | 43 |
| 41 std::vector<uint8_t> SHA256HashVec(const std::vector<uint8_t>& vec) { | 44 std::vector<uint8_t> SHA256HashVec(const std::vector<uint8_t>& vec) { |
| 42 if (vec.empty()) | 45 if (vec.empty()) |
| 43 return SHA256HashStr(base::StringPiece()); | 46 return SHA256HashStr(base::StringPiece()); |
| 44 | 47 |
| 45 return SHA256HashStr(base::StringPiece( | 48 return SHA256HashStr(base::StringPiece( |
| 46 reinterpret_cast<const char*>(&vec.front()), vec.size())); | 49 reinterpret_cast<const char*>(&vec.front()), vec.size())); |
| 47 } | 50 } |
| 48 | 51 |
| 49 bool ParseETagHeader(const base::StringPiece& etag_header_value, | 52 bool ParseETagHeader(const base::StringPiece& etag_header_value_in, |
| 50 std::vector<uint8_t>* ecdsa_signature_out, | 53 std::vector<uint8_t>* ecdsa_signature_out, |
| 51 std::vector<uint8_t>* request_hash_out) { | 54 std::vector<uint8_t>* request_hash_out) { |
| 52 DCHECK(ecdsa_signature_out); | 55 DCHECK(ecdsa_signature_out); |
| 53 DCHECK(request_hash_out); | 56 DCHECK(request_hash_out); |
| 54 | 57 |
| 55 // The ETag value is a UTF-8 string, formatted as "S:H", where: | 58 // The ETag value is a UTF-8 string, formatted as "S:H", where: |
| 56 // * S is the ECDSA signature in DER-encoded ASN.1 form, converted to hex. | 59 // * S is the ECDSA signature in DER-encoded ASN.1 form, converted to hex. |
| 57 // * H is the SHA-256 hash of the observed request body, standard hex format. | 60 // * H is the SHA-256 hash of the observed request body, standard hex format. |
| 61 // A Weak ETag is formatted as W/"S:H". This function treats it the same as a |
| 62 // strong ETag. |
| 63 base::StringPiece etag_header_value(etag_header_value_in); |
| 64 |
| 65 // Remove the weak prefix, then remove the begin and the end quotes. |
| 66 const char kWeakETagPrefix[] = "W/"; |
| 67 if (etag_header_value.starts_with(kWeakETagPrefix)) |
| 68 etag_header_value.remove_prefix(arraysize(kWeakETagPrefix) - 1); |
| 69 if (etag_header_value.size() >= 2 && etag_header_value.starts_with("\"") && |
| 70 etag_header_value.ends_with("\"")) { |
| 71 etag_header_value.remove_prefix(1); |
| 72 etag_header_value.remove_suffix(1); |
| 73 } |
| 74 |
| 58 const base::StringPiece::size_type delim_pos = etag_header_value.find(':'); | 75 const base::StringPiece::size_type delim_pos = etag_header_value.find(':'); |
| 59 if (delim_pos == base::StringPiece::npos || delim_pos == 0 || | 76 if (delim_pos == base::StringPiece::npos || delim_pos == 0 || |
| 60 delim_pos == etag_header_value.size() - 1) | 77 delim_pos == etag_header_value.size() - 1) |
| 61 return false; | 78 return false; |
| 62 | 79 |
| 63 const base::StringPiece sig_hex = etag_header_value.substr(0, delim_pos); | 80 const base::StringPiece sig_hex = etag_header_value.substr(0, delim_pos); |
| 64 const base::StringPiece hash_hex = etag_header_value.substr(delim_pos + 1); | 81 const base::StringPiece hash_hex = etag_header_value.substr(delim_pos + 1); |
| 65 | 82 |
| 66 // Decode the ECDSA signature. Don't bother validating the contents of it; | 83 // Decode the ECDSA signature. Don't bother validating the contents of it; |
| 67 // the SignatureValidator class will handle the actual DER decoding and | 84 // the SignatureValidator class will handle the actual DER decoding and |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 | 198 |
| 182 // If the verification fails, that implies one of two outcomes: | 199 // If the verification fails, that implies one of two outcomes: |
| 183 // * The signature was modified | 200 // * The signature was modified |
| 184 // * The buffer that the server signed does not match the buffer that the | 201 // * The buffer that the server signed does not match the buffer that the |
| 185 // client assembled -- implying that either request body or response body | 202 // client assembled -- implying that either request body or response body |
| 186 // was modified, or a different nonce value was used. | 203 // was modified, or a different nonce value was used. |
| 187 verifier.VerifyUpdate(&signed_message_hash.front(), | 204 verifier.VerifyUpdate(&signed_message_hash.front(), |
| 188 static_cast<int>(signed_message_hash.size())); | 205 static_cast<int>(signed_message_hash.size())); |
| 189 return verifier.VerifyFinal(); | 206 return verifier.VerifyFinal(); |
| 190 } | 207 } |
| 208 |
| 209 } // namespace update_client |
| OLD | NEW |