blob: fee72a91bfd7fbc7b95ffc76715cad9ea41e4959 [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) {
19 valid_ = (SHA1_Init(&ctx_) == 1);
20 LOG_IF(ERROR, !valid_) << "SHA1_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.
24// Mostly just passes the data through to OpenSSL's SHA1_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),
29 length_param_may_be_truncated_in_SHA1_Update);
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070030 TEST_AND_RETURN_FALSE(SHA1_Update(&ctx_, data, length) == 1);
31 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
35// calls OpenSSL's SHA1_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());
rspangler@google.com49fdf182009-10-10 00:57:34 +000039 unsigned char md[SHA_DIGEST_LENGTH];
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070040 TEST_AND_RETURN_FALSE(SHA1_Final(md, &ctx_) == 1);
rspangler@google.com49fdf182009-10-10 00:57:34 +000041
42 // Convert md to base64 encoding and store it in hash_
43 BIO *b64 = BIO_new(BIO_f_base64());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070044 if (!b64)
45 LOG(INFO) << "BIO_new(BIO_f_base64()) failed";
rspangler@google.com49fdf182009-10-10 00:57:34 +000046 BIO *bmem = BIO_new(BIO_s_mem());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070047 if (!bmem)
48 LOG(INFO) << "BIO_new(BIO_s_mem()) failed";
49 if (b64 && bmem) {
50 b64 = BIO_push(b64, bmem);
51 success = (BIO_write(b64, md, sizeof(md)) == sizeof(md));
52 if (success)
53 success = (BIO_flush(b64) == 1);
rspangler@google.com49fdf182009-10-10 00:57:34 +000054
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070055 BUF_MEM *bptr = NULL;
56 BIO_get_mem_ptr(b64, &bptr);
57 hash_.assign(bptr->data, bptr->length - 1);
58 }
59 if (b64) {
60 BIO_free_all(b64);
61 b64 = NULL;
62 }
63 return success;
rspangler@google.com49fdf182009-10-10 00:57:34 +000064}
65
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070066bool OmahaHashCalculator::RawHashOfData(const vector<char>& data,
67 vector<char>* out_hash) {
68 OmahaHashCalculator calc;
69 calc.Update(&data[0], data.size());
70
71 out_hash->resize(out_hash->size() + SHA_DIGEST_LENGTH);
72 TEST_AND_RETURN_FALSE(
73 SHA1_Final(reinterpret_cast<unsigned char*>(&(*(out_hash->end() -
74 SHA_DIGEST_LENGTH))),
75 &calc.ctx_) == 1);
76 return true;
77}
78
79string OmahaHashCalculator::OmahaHashOfBytes(
rspangler@google.com49fdf182009-10-10 00:57:34 +000080 const void* data, size_t length) {
81 OmahaHashCalculator calc;
82 calc.Update(reinterpret_cast<const char*>(data), length);
83 calc.Finalize();
84 return calc.hash();
85}
86
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070087string OmahaHashCalculator::OmahaHashOfString(const string& str) {
rspangler@google.com49fdf182009-10-10 00:57:34 +000088 return OmahaHashOfBytes(str.data(), str.size());
89}
90
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070091string OmahaHashCalculator::OmahaHashOfData(const vector<char>& data) {
rspangler@google.com49fdf182009-10-10 00:57:34 +000092 return OmahaHashOfBytes(&data[0], data.size());
93}
94
95} // namespace chromeos_update_engine