summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordavidben <davidben@chromium.org>2016-01-21 16:10:26 -0800
committerCommit bot <commit-bot@chromium.org>2016-01-22 00:12:34 +0000
commit626e8fad1311d7f5c51b809268f7c01d54bb8e9b (patch)
tree8ab9edd0f3822cf32f3d3bda55677b98ccebb158
parent494a77059cf199de5a6e11912fce2a155c868a26 (diff)
downloadchromium_src-626e8fad1311d7f5c51b809268f7c01d54bb8e9b.zip
chromium_src-626e8fad1311d7f5c51b809268f7c01d54bb8e9b.tar.gz
chromium_src-626e8fad1311d7f5c51b809268f7c01d54bb8e9b.tar.bz2
Remove crypto::GaloisHash.
This is no longer needed now that the Chimera has shipped. (iOS uses third_party/nss's AES-GCM implementation.) BUG=519504 Review URL: https://codereview.chromium.org/1616743003 Cr-Commit-Position: refs/heads/master@{#370842}
-rw-r--r--crypto/BUILD.gn3
-rw-r--r--crypto/crypto.gyp1
-rw-r--r--crypto/crypto.gypi2
-rw-r--r--crypto/ghash.cc262
-rw-r--r--crypto/ghash.h88
-rw-r--r--crypto/ghash_unittest.cc149
6 files changed, 0 insertions, 505 deletions
diff --git a/crypto/BUILD.gn b/crypto/BUILD.gn
index 8d24e60..34deeae 100644
--- a/crypto/BUILD.gn
+++ b/crypto/BUILD.gn
@@ -34,8 +34,6 @@ component("crypto") {
"encryptor.h",
"encryptor_nss.cc",
"encryptor_openssl.cc",
- "ghash.cc",
- "ghash.h",
"hkdf.cc",
"hkdf.h",
"hmac.cc",
@@ -244,7 +242,6 @@ test("crypto_unittests") {
"ec_private_key_unittest.cc",
"ec_signature_creator_unittest.cc",
"encryptor_unittest.cc",
- "ghash_unittest.cc",
"hkdf_unittest.cc",
"hmac_unittest.cc",
"nss_key_util_unittest.cc",
diff --git a/crypto/crypto.gyp b/crypto/crypto.gyp
index 2590c4f..f8b7967 100644
--- a/crypto/crypto.gyp
+++ b/crypto/crypto.gyp
@@ -169,7 +169,6 @@
'ec_private_key_unittest.cc',
'ec_signature_creator_unittest.cc',
'encryptor_unittest.cc',
- 'ghash_unittest.cc',
'hkdf_unittest.cc',
'hmac_unittest.cc',
'nss_key_util_unittest.cc',
diff --git a/crypto/crypto.gypi b/crypto/crypto.gypi
index e5cc4f44..2b9ce67 100644
--- a/crypto/crypto.gypi
+++ b/crypto/crypto.gypi
@@ -41,8 +41,6 @@
'curve25519.h',
'curve25519_nss.cc',
'curve25519_openssl.cc',
- 'ghash.cc',
- 'ghash.h',
'ec_private_key.h',
'ec_private_key_nss.cc',
'ec_private_key_openssl.cc',
diff --git a/crypto/ghash.cc b/crypto/ghash.cc
deleted file mode 100644
index fcd513e..0000000
--- a/crypto/ghash.cc
+++ /dev/null
@@ -1,262 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "crypto/ghash.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "base/sys_byteorder.h"
-
-namespace crypto {
-
-// GaloisHash is a polynomial authenticator that works in GF(2^128).
-//
-// Elements of the field are represented in `little-endian' order (which
-// matches the description in the paper[1]), thus the most significant bit is
-// the right-most bit. (This is backwards from the way that everybody else does
-// it.)
-//
-// We store field elements in a pair of such `little-endian' uint64s. So the
-// value one is represented by {low = 2**63, high = 0} and doubling a value
-// involves a *right* shift.
-//
-// [1] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
-
-namespace {
-
-// Get64 reads a 64-bit, big-endian number from |bytes|.
-uint64_t Get64(const uint8_t bytes[8]) {
- uint64_t t;
- memcpy(&t, bytes, sizeof(t));
- return base::NetToHost64(t);
-}
-
-// Put64 writes |x| to |bytes| as a 64-bit, big-endian number.
-void Put64(uint8_t bytes[8], uint64_t x) {
- x = base::HostToNet64(x);
- memcpy(bytes, &x, sizeof(x));
-}
-
-// Reverse reverses the order of the bits of 4-bit number in |i|.
-int Reverse(int i) {
- i = ((i << 2) & 0xc) | ((i >> 2) & 0x3);
- i = ((i << 1) & 0xa) | ((i >> 1) & 0x5);
- return i;
-}
-
-} // namespace
-
-GaloisHash::GaloisHash(const uint8_t key[16]) {
- Reset();
-
- // We precompute 16 multiples of |key|. However, when we do lookups into this
- // table we'll be using bits from a field element and therefore the bits will
- // be in the reverse order. So normally one would expect, say, 4*key to be in
- // index 4 of the table but due to this bit ordering it will actually be in
- // index 0010 (base 2) = 2.
- FieldElement x = {Get64(key), Get64(key+8)};
- product_table_[0].low = 0;
- product_table_[0].hi = 0;
- product_table_[Reverse(1)] = x;
-
- for (int i = 0; i < 16; i += 2) {
- product_table_[Reverse(i)] = Double(product_table_[Reverse(i/2)]);
- product_table_[Reverse(i+1)] = Add(product_table_[Reverse(i)], x);
- }
-}
-
-void GaloisHash::Reset() {
- state_ = kHashingAdditionalData;
- additional_bytes_ = 0;
- ciphertext_bytes_ = 0;
- buf_used_ = 0;
- y_.low = 0;
- y_.hi = 0;
-}
-
-void GaloisHash::UpdateAdditional(const uint8_t* data, size_t length) {
- DCHECK_EQ(state_, kHashingAdditionalData);
- additional_bytes_ += length;
- Update(data, length);
-}
-
-void GaloisHash::UpdateCiphertext(const uint8_t* data, size_t length) {
- if (state_ == kHashingAdditionalData) {
- // If there's any remaining additional data it's zero padded to the next
- // full block.
- if (buf_used_ > 0) {
- memset(&buf_[buf_used_], 0, sizeof(buf_)-buf_used_);
- UpdateBlocks(buf_, 1);
- buf_used_ = 0;
- }
- state_ = kHashingCiphertext;
- }
-
- DCHECK_EQ(state_, kHashingCiphertext);
- ciphertext_bytes_ += length;
- Update(data, length);
-}
-
-void GaloisHash::Finish(void* output, size_t len) {
- DCHECK(state_ != kComplete);
-
- if (buf_used_ > 0) {
- // If there's any remaining data (additional data or ciphertext), it's zero
- // padded to the next full block.
- memset(&buf_[buf_used_], 0, sizeof(buf_)-buf_used_);
- UpdateBlocks(buf_, 1);
- buf_used_ = 0;
- }
-
- state_ = kComplete;
-
- // The lengths of the additional data and ciphertext are included as the last
- // block. The lengths are the number of bits.
- y_.low ^= additional_bytes_*8;
- y_.hi ^= ciphertext_bytes_*8;
- MulAfterPrecomputation(product_table_, &y_);
-
- uint8_t *result, result_tmp[16];
- if (len >= 16) {
- result = reinterpret_cast<uint8_t*>(output);
- } else {
- result = result_tmp;
- }
-
- Put64(result, y_.low);
- Put64(result + 8, y_.hi);
-
- if (len < 16)
- memcpy(output, result_tmp, len);
-}
-
-// static
-GaloisHash::FieldElement GaloisHash::Add(
- const FieldElement& x,
- const FieldElement& y) {
- // Addition in a characteristic 2 field is just XOR.
- FieldElement z = {x.low^y.low, x.hi^y.hi};
- return z;
-}
-
-// static
-GaloisHash::FieldElement GaloisHash::Double(const FieldElement& x) {
- const bool msb_set = x.hi & 1;
-
- FieldElement xx;
- // Because of the bit-ordering, doubling is actually a right shift.
- xx.hi = x.hi >> 1;
- xx.hi |= x.low << 63;
- xx.low = x.low >> 1;
-
- // If the most-significant bit was set before shifting then it, conceptually,
- // becomes a term of x^128. This is greater than the irreducible polynomial
- // so the result has to be reduced. The irreducible polynomial is
- // 1+x+x^2+x^7+x^128. We can subtract that to eliminate the term at x^128
- // which also means subtracting the other four terms. In characteristic 2
- // fields, subtraction == addition == XOR.
- if (msb_set)
- xx.low ^= 0xe100000000000000ULL;
-
- return xx;
-}
-
-void GaloisHash::MulAfterPrecomputation(const FieldElement* table,
- FieldElement* x) {
- FieldElement z = {0, 0};
-
- // In order to efficiently multiply, we use the precomputed table of i*key,
- // for i in 0..15, to handle four bits at a time. We could obviously use
- // larger tables for greater speedups but the next convenient table size is
- // 4K, which is a little large.
- //
- // In other fields one would use bit positions spread out across the field in
- // order to reduce the number of doublings required. However, in
- // characteristic 2 fields, repeated doublings are exceptionally cheap and
- // it's not worth spending more precomputation time to eliminate them.
- for (unsigned i = 0; i < 2; i++) {
- uint64_t word;
- if (i == 0) {
- word = x->hi;
- } else {
- word = x->low;
- }
-
- for (unsigned j = 0; j < 64; j += 4) {
- Mul16(&z);
- // the values in |table| are ordered for little-endian bit positions. See
- // the comment in the constructor.
- const FieldElement& t = table[word & 0xf];
- z.low ^= t.low;
- z.hi ^= t.hi;
- word >>= 4;
- }
- }
-
- *x = z;
-}
-
-// kReductionTable allows for rapid multiplications by 16. A multiplication by
-// 16 is a right shift by four bits, which results in four bits at 2**128.
-// These terms have to be eliminated by dividing by the irreducible polynomial.
-// In GHASH, the polynomial is such that all the terms occur in the
-// least-significant 8 bits, save for the term at x^128. Therefore we can
-// precompute the value to be added to the field element for each of the 16 bit
-// patterns at 2**128 and the values fit within 12 bits.
-static const uint16_t kReductionTable[16] = {
- 0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0,
- 0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0,
-};
-
-// static
-void GaloisHash::Mul16(FieldElement* x) {
- const unsigned msw = x->hi & 0xf;
- x->hi >>= 4;
- x->hi |= x->low << 60;
- x->low >>= 4;
- x->low ^= static_cast<uint64_t>(kReductionTable[msw]) << 48;
-}
-
-void GaloisHash::UpdateBlocks(const uint8_t* bytes, size_t num_blocks) {
- for (size_t i = 0; i < num_blocks; i++) {
- y_.low ^= Get64(bytes);
- bytes += 8;
- y_.hi ^= Get64(bytes);
- bytes += 8;
- MulAfterPrecomputation(product_table_, &y_);
- }
-}
-
-void GaloisHash::Update(const uint8_t* data, size_t length) {
- if (buf_used_ > 0) {
- const size_t n = std::min(length, sizeof(buf_) - buf_used_);
- memcpy(&buf_[buf_used_], data, n);
- buf_used_ += n;
- length -= n;
- data += n;
-
- if (buf_used_ == sizeof(buf_)) {
- UpdateBlocks(buf_, 1);
- buf_used_ = 0;
- }
- }
-
- if (length >= 16) {
- const size_t n = length / 16;
- UpdateBlocks(data, n);
- length -= n*16;
- data += n*16;
- }
-
- if (length > 0) {
- memcpy(buf_, data, length);
- buf_used_ = length;
- }
-}
-
-} // namespace crypto
diff --git a/crypto/ghash.h b/crypto/ghash.h
deleted file mode 100644
index b123dfe..0000000
--- a/crypto/ghash.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "crypto/crypto_export.h"
-
-namespace crypto {
-
-// GaloisHash implements the polynomial authenticator part of GCM as specified
-// in http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
-// Specifically it implements the GHASH function, defined in section 2.3 of
-// that document.
-//
-// In SP-800-38D, GHASH is defined differently and takes only a single data
-// argument. But it is always called with an argument of a certain form:
-// GHASH_H (A || 0^v || C || 0^u || [len(A)]_64 || [len(C)]_64)
-// This mirrors how the gcm-revised-spec.pdf version of GHASH handles its two
-// data arguments. The two GHASH functions therefore differ only in whether the
-// data is formatted inside or outside of the function.
-//
-// WARNING: do not use this as a generic authenticator. Polynomial
-// authenticators must be used in the correct manner and any use outside of GCM
-// requires careful consideration.
-//
-// WARNING: this code is not constant time. However, in all likelihood, nor is
-// the implementation of AES that is used.
-class CRYPTO_EXPORT GaloisHash {
- public:
- explicit GaloisHash(const uint8_t key[16]);
-
- // Reset prepares to digest a fresh message with the same key. This is more
- // efficient than creating a fresh object.
- void Reset();
-
- // UpdateAdditional hashes in `additional' data. This is data that is not
- // encrypted, but is covered by the authenticator. All additional data must
- // be written before any ciphertext is written.
- void UpdateAdditional(const uint8_t* data, size_t length);
-
- // UpdateCiphertext hashes in ciphertext to be authenticated.
- void UpdateCiphertext(const uint8_t* data, size_t length);
-
- // Finish completes the hash computation and writes at most |len| bytes of
- // the result to |output|.
- void Finish(void* output, size_t len);
-
- private:
- enum State {
- kHashingAdditionalData,
- kHashingCiphertext,
- kComplete,
- };
-
- struct FieldElement {
- uint64_t low, hi;
- };
-
- // Add returns |x|+|y|.
- static FieldElement Add(const FieldElement& x, const FieldElement& y);
- // Double returns 2*|x|.
- static FieldElement Double(const FieldElement& x);
- // MulAfterPrecomputation sets |x| = |x|*h where h is |table[1]| and
- // table[i] = i*h for i=0..15.
- static void MulAfterPrecomputation(const FieldElement* table,
- FieldElement* x);
- // Mul16 sets |x| = 16*|x|.
- static void Mul16(FieldElement* x);
-
- // UpdateBlocks processes |num_blocks| 16-bytes blocks from |bytes|.
- void UpdateBlocks(const uint8_t* bytes, size_t num_blocks);
- // Update processes |length| bytes from |bytes| and calls UpdateBlocks on as
- // much data as possible. It uses |buf_| to buffer any remaining data and
- // always consumes all of |bytes|.
- void Update(const uint8_t* bytes, size_t length);
-
- FieldElement y_;
- State state_;
- size_t additional_bytes_;
- size_t ciphertext_bytes_;
- uint8_t buf_[16];
- size_t buf_used_;
- FieldElement product_table_[16];
-};
-
-} // namespace crypto
diff --git a/crypto/ghash_unittest.cc b/crypto/ghash_unittest.cc
deleted file mode 100644
index 01f9cf4..0000000
--- a/crypto/ghash_unittest.cc
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "crypto/ghash.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <algorithm>
-
-#include "base/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace crypto {
-
-namespace {
-
-// Test vectors are taken from Appendix B of
-// http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
-
-static const uint8_t kKey1[16] = {
- 0x66, 0xe9, 0x4b, 0xd4, 0xef, 0x8a, 0x2c, 0x3b,
- 0x88, 0x4c, 0xfa, 0x59, 0xca, 0x34, 0x2b, 0x2e,
-};
-
-static const uint8_t kCiphertext2[] = {
- 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
- 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78,
-};
-
-static const uint8_t kKey3[16] = {
- 0xb8, 0x3b, 0x53, 0x37, 0x08, 0xbf, 0x53, 0x5d,
- 0x0a, 0xa6, 0xe5, 0x29, 0x80, 0xd5, 0x3b, 0x78,
-};
-
-static const uint8_t kCiphertext3[] = {
- 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21,
- 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02,
- 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 0x21,
- 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f, 0x6a, 0x5a,
- 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac,
- 0x97, 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85,
-};
-
-static const uint8_t kAdditional4[] = {
- 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed,
- 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
-};
-
-struct TestCase {
- const uint8_t* key;
- const uint8_t* additional;
- unsigned additional_length;
- const uint8_t* ciphertext;
- unsigned ciphertext_length;
- const uint8_t expected[16];
-};
-
-static const TestCase kTestCases[] = {
- {
- kKey1,
- NULL,
- 0,
- NULL,
- 0,
- {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- },
- },
- {
- kKey1,
- NULL,
- 0,
- kCiphertext2,
- sizeof(kCiphertext2),
- {
- 0xf3, 0x8c, 0xbb, 0x1a, 0xd6, 0x92, 0x23, 0xdc,
- 0xc3, 0x45, 0x7a, 0xe5, 0xb6, 0xb0, 0xf8, 0x85,
- },
- },
- {
- kKey3,
- NULL,
- 0,
- kCiphertext3,
- sizeof(kCiphertext3),
- {
- 0x7f, 0x1b, 0x32, 0xb8, 0x1b, 0x82, 0x0d, 0x02,
- 0x61, 0x4f, 0x88, 0x95, 0xac, 0x1d, 0x4e, 0xac,
- },
- },
- {
- kKey3,
- kAdditional4,
- sizeof(kAdditional4),
- kCiphertext3,
- sizeof(kCiphertext3) - 4,
- {
- 0x69, 0x8e, 0x57, 0xf7, 0x0e, 0x6e, 0xcc, 0x7f,
- 0xd9, 0x46, 0x3b, 0x72, 0x60, 0xa9, 0xae, 0x5f,
- },
- },
-};
-
-TEST(GaloisHash, TestCases) {
- uint8_t out[16];
-
- for (size_t i = 0; i < arraysize(kTestCases); ++i) {
- const TestCase& test = kTestCases[i];
-
- GaloisHash hash(test.key);
- if (test.additional_length)
- hash.UpdateAdditional(test.additional, test.additional_length);
- if (test.ciphertext_length)
- hash.UpdateCiphertext(test.ciphertext, test.ciphertext_length);
- hash.Finish(out, sizeof(out));
- EXPECT_TRUE(0 == memcmp(out, test.expected, 16));
- }
-}
-
-TEST(GaloisHash, VaryLengths) {
- uint8_t out[16];
-
- for (size_t chunk_size = 1; chunk_size < 16; chunk_size++) {
- for (size_t i = 0; i < arraysize(kTestCases); ++i) {
- const TestCase& test = kTestCases[i];
-
- GaloisHash hash(test.key);
- for (size_t i = 0; i < test.additional_length;) {
- size_t n = std::min(test.additional_length - i, chunk_size);
- hash.UpdateAdditional(test.additional + i, n);
- i += n;
- }
- for (size_t i = 0; i < test.ciphertext_length;) {
- size_t n = std::min(test.ciphertext_length - i, chunk_size);
- hash.UpdateCiphertext(test.ciphertext + i, n);
- i += n;
- }
- hash.Finish(out, sizeof(out));
- EXPECT_TRUE(0 == memcmp(out, test.expected, 16));
- }
- }
-}
-
-} // namespace
-
-} // namespace crypto