sha1_portable.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sha1.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Implementation of SHA-1. Only handles data in byte-sized blocks,
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which simplifies the code a fair bit.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Identifier names follow notation in FIPS PUB 180-3, where you'll
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// also find a description of the algorithm:
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Usage example:
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SecureHashAlgorithm sha;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// while(there is data to hash)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   sha.Update(moredata, size of data);
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sha.Final();
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// memcpy(somewhere, sha.Digest(), 20);
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to reuse the instance of sha, call sha.Init();
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(jhawkins): Replace this implementation with a per-platform
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// implementation using each platform's crypto library.  See
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://crbug.com/47218
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SecureHashAlgorithm {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SecureHashAlgorithm() { Init(); }
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kDigestSizeBytes;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Init();
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Update(const void* data, size_t nbytes);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Final();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 20 bytes of message digest.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const unsigned char* Digest() const {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<const unsigned char*>(H);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Pad();
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Process();
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 A, B, C, D, E;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 H[5];
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  union {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 W[80];
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8 M[64];
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 cursor;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 l;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline uint32 f(uint32 t, uint32 B, uint32 C, uint32 D) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (t < 20) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (B & C) | ((~B) & D);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (t < 40) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return B ^ C ^ D;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (t < 60) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (B & C) | (B & D) | (C & D);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return B ^ C ^ D;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline uint32 S(uint32 n, uint32 X) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (X << n) | (X >> (32-n));
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline uint32 K(uint32 t) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (t < 20) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0x5a827999;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (t < 40) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0x6ed9eba1;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (t < 60) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0x8f1bbcdc;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0xca62c1d6;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline void swapends(uint32* t) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *t = ((*t & 0xff000000) >> 24) |
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ((*t & 0xff0000) >> 8) |
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ((*t & 0xff00) << 8) |
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ((*t & 0xff) << 24);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int SecureHashAlgorithm::kDigestSizeBytes = 20;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SecureHashAlgorithm::Init() {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  A = 0;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  B = 0;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  C = 0;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  D = 0;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  E = 0;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cursor = 0;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  l = 0;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  H[0] = 0x67452301;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  H[1] = 0xefcdab89;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  H[2] = 0x98badcfe;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  H[3] = 0x10325476;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  H[4] = 0xc3d2e1f0;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SecureHashAlgorithm::Final() {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pad();
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Process();
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int t = 0; t < 5; ++t)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    swapends(&H[t]);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SecureHashAlgorithm::Update(const void* data, size_t nbytes) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8* d = reinterpret_cast<const uint8*>(data);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (nbytes--) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    M[cursor++] = *d++;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cursor >= 64)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Process();
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    l += 8;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SecureHashAlgorithm::Pad() {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  M[cursor++] = 0x80;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cursor > 64-8) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // pad out to next block
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (cursor < 64)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      M[cursor++] = 0;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Process();
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (cursor < 64-4)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    M[cursor++] = 0;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  M[64-4] = (l & 0xff000000) >> 24;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  M[64-3] = (l & 0xff0000) >> 16;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  M[64-2] = (l & 0xff00) >> 8;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  M[64-1] = (l & 0xff);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SecureHashAlgorithm::Process() {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 t;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Each a...e corresponds to a section in the FIPS 180-3 algorithm.
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a.
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // W and M are in a union, so no need to memcpy.
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // memcpy(W, M, sizeof(M));
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (t = 0; t < 16; ++t)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    swapends(&W[t]);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // b.
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (t = 16; t < 80; ++t)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    W[t] = S(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // c.
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  A = H[0];
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  B = H[1];
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  C = H[2];
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  D = H[3];
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  E = H[4];
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // d.
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (t = 0; t < 80; ++t) {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 TEMP = S(5, A) + f(t, B, C, D) + E + W[t] + K(t);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    E = D;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    D = C;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    C = S(30, B);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    B = A;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    A = TEMP;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // e.
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  H[0] += A;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  H[1] += B;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  H[2] += C;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  H[3] += D;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  H[4] += E;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cursor = 0;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string SHA1HashString(const std::string& str) {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char hash[SecureHashAlgorithm::kDigestSizeBytes];
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SHA1HashBytes(reinterpret_cast<const unsigned char*>(str.c_str()),
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                str.length(), reinterpret_cast<unsigned char*>(hash));
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::string(hash, SecureHashAlgorithm::kDigestSizeBytes);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SHA1HashBytes(const unsigned char* data, size_t len,
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   unsigned char* hash) {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SecureHashAlgorithm sha;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sha.Update(data, len);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sha.Final();
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(hash, sha.Digest(), SecureHashAlgorithm::kDigestSizeBytes);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
216