blob: 0df83bcd99598ba99f1a0697a6b16657401ae71e [file] [log] [blame]
rspangler@google.com49fdf182009-10-10 00:57:34 +00001// Copyright (c) 2009 The Chromium OS 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
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -07005#include "update_engine/omaha_hash_calculator.h"
6
rspangler@google.com49fdf182009-10-10 00:57:34 +00007#include <openssl/bio.h>
8#include <openssl/buffer.h>
9#include <openssl/evp.h>
Chris Masone790e62e2010-08-12 10:41:18 -070010#include "base/logging.h"
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070011#include "update_engine/utils.h"
12
13using std::string;
14using std::vector;
rspangler@google.com49fdf182009-10-10 00:57:34 +000015
16namespace chromeos_update_engine {
17
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070018OmahaHashCalculator::OmahaHashCalculator() : valid_(false) {
Darin Petkovd22cb292010-09-29 10:02:29 -070019 valid_ = (SHA256_Init(&ctx_) == 1);
20 LOG_IF(ERROR, !valid_) << "SHA256_Init failed";
rspangler@google.com49fdf182009-10-10 00:57:34 +000021}
22
23// Update is called with all of the data that should be hashed in order.
Darin Petkovd22cb292010-09-29 10:02:29 -070024// Mostly just passes the data through to OpenSSL's SHA256_Update()
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070025bool OmahaHashCalculator::Update(const char* data, size_t length) {
26 TEST_AND_RETURN_FALSE(valid_);
27 TEST_AND_RETURN_FALSE(hash_.empty());
rspangler@google.com49fdf182009-10-10 00:57:34 +000028 COMPILE_ASSERT(sizeof(size_t) <= sizeof(unsigned long),
Darin Petkovd22cb292010-09-29 10:02:29 -070029 length_param_may_be_truncated_in_SHA256_Update);
30 TEST_AND_RETURN_FALSE(SHA256_Update(&ctx_, data, length) == 1);
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070031 return true;
rspangler@google.com49fdf182009-10-10 00:57:34 +000032}
33
34// Call Finalize() when all data has been passed in. This mostly just
Darin Petkovd22cb292010-09-29 10:02:29 -070035// calls OpenSSL's SHA256_Final() and then base64 encodes the hash.
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070036bool OmahaHashCalculator::Finalize() {
37 bool success = true;
38 TEST_AND_RETURN_FALSE(hash_.empty());
Darin Petkovd7061ab2010-10-06 14:37:09 -070039 TEST_AND_RETURN_FALSE(raw_hash_.empty());
40 raw_hash_.resize(SHA256_DIGEST_LENGTH);
41 TEST_AND_RETURN_FALSE(
42 SHA256_Final(reinterpret_cast<unsigned char*>(&raw_hash_[0]),
43 &ctx_) == 1);
rspangler@google.com49fdf182009-10-10 00:57:34 +000044
Darin Petkovd7061ab2010-10-06 14:37:09 -070045 // Convert raw_hash_ to base64 encoding and store it in hash_.
rspangler@google.com49fdf182009-10-10 00:57:34 +000046 BIO *b64 = BIO_new(BIO_f_base64());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070047 if (!b64)
48 LOG(INFO) << "BIO_new(BIO_f_base64()) failed";
rspangler@google.com49fdf182009-10-10 00:57:34 +000049 BIO *bmem = BIO_new(BIO_s_mem());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070050 if (!bmem)
51 LOG(INFO) << "BIO_new(BIO_s_mem()) failed";
52 if (b64 && bmem) {
53 b64 = BIO_push(b64, bmem);
Darin Petkovd7061ab2010-10-06 14:37:09 -070054 success =
55 (BIO_write(b64, &raw_hash_[0], raw_hash_.size()) ==
56 static_cast<int>(raw_hash_.size()));
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070057 if (success)
58 success = (BIO_flush(b64) == 1);
rspangler@google.com49fdf182009-10-10 00:57:34 +000059
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070060 BUF_MEM *bptr = NULL;
61 BIO_get_mem_ptr(b64, &bptr);
62 hash_.assign(bptr->data, bptr->length - 1);
63 }
64 if (b64) {
65 BIO_free_all(b64);
66 b64 = NULL;
67 }
68 return success;
rspangler@google.com49fdf182009-10-10 00:57:34 +000069}
70
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070071bool OmahaHashCalculator::RawHashOfData(const vector<char>& data,
72 vector<char>* out_hash) {
73 OmahaHashCalculator calc;
74 calc.Update(&data[0], data.size());
Darin Petkovd22cb292010-09-29 10:02:29 -070075
76 out_hash->resize(out_hash->size() + SHA256_DIGEST_LENGTH);
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070077 TEST_AND_RETURN_FALSE(
Darin Petkovd22cb292010-09-29 10:02:29 -070078 SHA256_Final(reinterpret_cast<unsigned char*>(&(*(out_hash->end() -
79 SHA256_DIGEST_LENGTH))),
80 &calc.ctx_) == 1);
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070081 return true;
82}
83
84string OmahaHashCalculator::OmahaHashOfBytes(
rspangler@google.com49fdf182009-10-10 00:57:34 +000085 const void* data, size_t length) {
86 OmahaHashCalculator calc;
87 calc.Update(reinterpret_cast<const char*>(data), length);
88 calc.Finalize();
89 return calc.hash();
90}
91
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070092string OmahaHashCalculator::OmahaHashOfString(const string& str) {
rspangler@google.com49fdf182009-10-10 00:57:34 +000093 return OmahaHashOfBytes(str.data(), str.size());
94}
95
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070096string OmahaHashCalculator::OmahaHashOfData(const vector<char>& data) {
rspangler@google.com49fdf182009-10-10 00:57:34 +000097 return OmahaHashOfBytes(&data[0], data.size());
98}
99
100} // namespace chromeos_update_engine