mincrypt: support SHA-256 hash algorithm

- adds a library to compute the SHA-256 hash

- updates the RSA verifier to take an argument specifying either SHA-1
  or SHA-256

- updates DumpPublicKey to with new "key" version numbers for
  specifying SHA-256

- adds new argument to adb auth code to maintain existing behavior

Change-Id: I5b1406cf57c2b8993f6032eda3e29139f7740839
This commit is contained in:
Doug Zongker 2013-04-10 09:22:02 -07:00
parent 5cad711976
commit 515e1639ef
12 changed files with 465 additions and 268 deletions

View file

@ -25,6 +25,7 @@
#include "adb_auth.h"
#include "fdevent.h"
#include "mincrypt/rsa.h"
#include "mincrypt/sha.h"
#define TRACE_TAG TRACE_AUTH
@ -149,7 +150,7 @@ int adb_auth_verify(void *token, void *sig, int siglen)
list_for_each(item, &key_list) {
key = node_to_item(item, struct adb_public_key, node);
ret = RSA_verify(&key->key, sig, siglen, token);
ret = RSA_verify(&key->key, sig, siglen, token, SHA_DIGEST_SIZE);
if (ret)
break;
}

View file

@ -0,0 +1,40 @@
// Copyright 2007 Google Inc. All Rights Reserved.
// Author: mschilder@google.com (Marius Schilder)
#ifndef SECURITY_UTIL_LITE_HASH_INTERNAL_H__
#define SECURITY_UTIL_LITE_HASH_INTERNAL_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
struct HASH_CTX; // forward decl
typedef struct HASH_VTAB {
void (* const init)(struct HASH_CTX*);
void (* const update)(struct HASH_CTX*, const void*, int);
const uint8_t* (* const final)(struct HASH_CTX*);
const uint8_t* (* const hash)(const void*, int, uint8_t*);
int size;
} HASH_VTAB;
typedef struct HASH_CTX {
const HASH_VTAB * f;
uint64_t count;
uint8_t buf[64];
uint32_t state[8]; // upto SHA2
} HASH_CTX;
#define HASH_init(ctx) (ctx)->f->init(ctx)
#define HASH_update(ctx, data, len) (ctx)->f->update(ctx, data, len)
#define HASH_final(ctx) (ctx)->f->final(ctx)
#define HASH_hash(data, len, digest) (ctx)->f->hash(data, len, digest)
#define HASH_size(ctx) (ctx)->f->size
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // SECURITY_UTIL_LITE_HASH_INTERNAL_H__

View file

@ -48,7 +48,8 @@ typedef struct RSAPublicKey {
int RSA_verify(const RSAPublicKey *key,
const uint8_t* signature,
const int len,
const uint8_t* sha);
const uint8_t* hash,
const int hash_len);
#ifdef __cplusplus
}

View file

@ -1,63 +1,30 @@
/* sha.h
**
** Copyright 2008, The Android Open Source Project
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of Google Inc. nor the names of its contributors may
** be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Copyright 2005 Google Inc. All Rights Reserved.
// Author: mschilder@google.com (Marius Schilder)
#ifndef _EMBEDDED_SHA_H_
#define _EMBEDDED_SHA_H_
#ifndef SECURITY_UTIL_LITE_SHA1_H__
#define SECURITY_UTIL_LITE_SHA1_H__
#include <inttypes.h>
#include <stdint.h>
#include "hash-internal.h"
#ifdef __cplusplus
extern "C" {
#endif
#endif // __cplusplus
typedef struct SHA_CTX {
uint64_t count;
uint32_t state[5];
#if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN)
union {
uint8_t b[64];
uint32_t w[16];
} buf;
#else
uint8_t buf[64];
#endif
} SHA_CTX;
typedef HASH_CTX SHA_CTX;
void SHA_init(SHA_CTX* ctx);
void SHA_update(SHA_CTX* ctx, const void* data, int len);
const uint8_t* SHA_final(SHA_CTX* ctx);
/* Convenience method. Returns digest parameter value. */
const uint8_t* SHA(const void* data, int len, uint8_t* digest);
// Convenience method. Returns digest address.
// NOTE: *digest needs to hold SHA_DIGEST_SIZE bytes.
const uint8_t* SHA_hash(const void* data, int len, uint8_t* digest);
#define SHA_DIGEST_SIZE 20
#ifdef __cplusplus
}
#endif
#endif // __cplusplus
#endif
#endif // SECURITY_UTIL_LITE_SHA1_H__

29
include/mincrypt/sha256.h Normal file
View file

@ -0,0 +1,29 @@
// Copyright 2011 Google Inc. All Rights Reserved.
// Author: mschilder@google.com (Marius Schilder)
#ifndef SECURITY_UTIL_LITE_SHA256_H__
#define SECURITY_UTIL_LITE_SHA256_H__
#include <stdint.h>
#include "hash-internal.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
typedef HASH_CTX SHA256_CTX;
void SHA256_init(SHA256_CTX* ctx);
void SHA256_update(SHA256_CTX* ctx, const void* data, int len);
const uint8_t* SHA256_final(SHA256_CTX* ctx);
// Convenience method. Returns digest address.
const uint8_t* SHA256_hash(const void* data, int len, uint8_t* digest);
#define SHA256_DIGEST_SIZE 32
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // SECURITY_UTIL_LITE_SHA256_H__

View file

@ -4,13 +4,13 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libmincrypt
LOCAL_SRC_FILES := rsa.c rsa_e_3.c rsa_e_f4.c sha.c
LOCAL_SRC_FILES := rsa.c rsa_e_3.c rsa_e_f4.c sha.c sha256.c
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libmincrypt
LOCAL_SRC_FILES := rsa.c rsa_e_3.c rsa_e_f4.c sha.c
LOCAL_SRC_FILES := rsa.c rsa_e_3.c rsa_e_f4.c sha.c sha256.c
include $(BUILD_HOST_STATIC_LIBRARY)

View file

@ -30,23 +30,26 @@
int RSA_e_f4_verify(const RSAPublicKey* key,
const uint8_t* signature,
const int len,
const uint8_t* sha);
const uint8_t* hash,
const int hash_len);
int RSA_e_3_verify(const RSAPublicKey *key,
const uint8_t *signature,
const int len,
const uint8_t *sha);
const uint8_t *hash,
const int hash_len);
int RSA_verify(const RSAPublicKey *key,
const uint8_t *signature,
const int len,
const uint8_t *sha) {
const uint8_t *hash,
const int hash_len) {
switch (key->exponent) {
case 3:
return RSA_e_3_verify(key, signature, len, sha);
return RSA_e_3_verify(key, signature, len, hash, hash_len);
break;
case 65537:
return RSA_e_f4_verify(key, signature, len, sha);
return RSA_e_f4_verify(key, signature, len, hash, hash_len);
break;
default:
return 0;

View file

@ -27,6 +27,7 @@
#include "mincrypt/rsa.h"
#include "mincrypt/sha.h"
#include "mincrypt/sha256.h"
/* a[] -= mod */
static void subM(const RSAPublicKey *key, uint32_t *a) {
@ -134,7 +135,7 @@ static void modpow3(const RSAPublicKey *key,
** other flavor which omits the optional parameter entirely). This code does not
** accept signatures without the optional parameter.
*/
static const uint8_t padding[RSANUMBYTES - SHA_DIGEST_SIZE] = {
static const uint8_t sha_padding[RSANUMBYTES - SHA_DIGEST_SIZE] = {
0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
@ -156,15 +157,56 @@ static const uint8_t padding[RSANUMBYTES - SHA_DIGEST_SIZE] = {
0x04,0x14
};
static const uint8_t sha256_padding[RSANUMBYTES - SHA256_DIGEST_SIZE] = {
0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x30,0x31,0x30,
0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,
0x00,0x04,0x20
};
/* Verify a 2048 bit RSA e=3 PKCS1.5 signature against an expected SHA-1 hash.
** Returns 0 on failure, 1 on success.
*/
int RSA_e_3_verify(const RSAPublicKey *key,
const uint8_t *signature,
const int len,
const uint8_t *sha) {
const uint8_t *hash,
const int hash_len) {
uint8_t buf[RSANUMBYTES];
int i;
int padding_size;
const uint8_t* padding;
switch (hash_len) {
case SHA_DIGEST_SIZE:
padding = sha_padding;
padding_size = sizeof(sha_padding);
break;
case SHA256_DIGEST_SIZE:
padding = sha256_padding;
padding_size = sizeof(sha256_padding);
break;
default:
return 0; // unsupported hash
}
if (key->len != RSANUMWORDS) {
return 0; /* Wrong key passed in. */
@ -185,7 +227,7 @@ int RSA_e_3_verify(const RSAPublicKey *key,
modpow3(key, buf);
/* Check pkcs1.5 padding bytes. */
for (i = 0; i < (int) sizeof(padding); ++i) {
for (i = 0; i < padding_size; ++i) {
if (buf[i] != padding[i]) {
return 0;
}
@ -193,7 +235,7 @@ int RSA_e_3_verify(const RSAPublicKey *key,
/* Check sha digest matches. */
for (; i < len; ++i) {
if (buf[i] != *sha++) {
if (buf[i] != *hash++) {
return 0;
}
}

View file

@ -27,6 +27,7 @@
#include "mincrypt/rsa.h"
#include "mincrypt/sha.h"
#include "mincrypt/sha256.h"
// a[] -= mod
static void subM(const RSAPublicKey* key,
@ -138,26 +139,79 @@ static void modpowF4(const RSAPublicKey* key,
// other flavor which omits the optional parameter entirely). This code does not
// accept signatures without the optional parameter.
/*
static const uint8_t padding[RSANUMBYTES] = {
static const uint8_t sha_padding[RSANUMBYTES] = {
0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
static const uint8_t sha256_padding[RSANUMBYTES] = {
0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x30,0x31,0x30,
0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,
0x00,0x04,0x20,
// 32 bytes of hash go here.
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
};
*/
// SHA-1 of PKCS1.5 signature padding for 2048 bit, as above.
// SHA-1 of PKCS1.5 signature sha_padding for 2048 bit, as above.
// At the location of the bytes of the hash all 00 are hashed.
static const uint8_t kExpectedPadShaRsa2048[SHA_DIGEST_SIZE] = {
0xdc, 0xbd, 0xbe, 0x42, 0xd5, 0xf5, 0xa7, 0x2e, 0x6e, 0xfc,
0xf5, 0x5d, 0xaf, 0x9d, 0xea, 0x68, 0x7c, 0xfb, 0xf1, 0x67
};
// SHA-256 of PKCS1.5 signature sha256_padding for 2048 bit, as above.
// At the location of the bytes of the hash all 00 are hashed.
static const uint8_t kExpectedPadSha256Rsa2048[SHA256_DIGEST_SIZE] = {
0xab, 0x28, 0x8d, 0x8a, 0xd7, 0xd9, 0x59, 0x92,
0xba, 0xcc, 0xf8, 0x67, 0x20, 0xe1, 0x15, 0x2e,
0x39, 0x8d, 0x80, 0x36, 0xd6, 0x6f, 0xf0, 0xfd,
0x90, 0xe8, 0x7d, 0x8b, 0xe1, 0x7c, 0x87, 0x59,
};
// Verify a 2048 bit RSA e=65537 PKCS1.5 signature against an expected
// SHA-1 hash. Returns 0 on failure, 1 on success.
int RSA_e_f4_verify(const RSAPublicKey* key,
const uint8_t* signature,
const int len,
const uint8_t* sha) {
const uint8_t* hash,
const int hash_len) {
uint8_t buf[RSANUMBYTES];
int i;
const uint8_t* padding_hash;
switch (hash_len) {
case SHA_DIGEST_SIZE:
padding_hash = kExpectedPadShaRsa2048;
break;
case SHA256_DIGEST_SIZE:
padding_hash = kExpectedPadSha256Rsa2048;
break;
default:
return 0; // unsupported hash
}
if (key->len != RSANUMWORDS) {
return 0; // Wrong key passed in.
@ -178,16 +232,25 @@ int RSA_e_f4_verify(const RSAPublicKey* key,
modpowF4(key, buf); // In-place exponentiation.
// Xor sha portion, so it all becomes 00 iff equal.
for (i = len - SHA_DIGEST_SIZE; i < len; ++i) {
buf[i] ^= *sha++;
for (i = len - hash_len; i < len; ++i) {
buf[i] ^= *hash++;
}
// Hash resulting buf, in-place.
SHA(buf, len, buf);
switch (hash_len) {
case SHA_DIGEST_SIZE:
SHA_hash(buf, len, buf);
break;
case SHA256_DIGEST_SIZE:
SHA256_hash(buf, len, buf);
break;
default:
return 0;
}
// Compare against expected hash value.
for (i = 0; i < SHA_DIGEST_SIZE; ++i) {
if (buf[i] != kExpectedPadShaRsa2048[i]) {
for (i = 0; i < hash_len; ++i) {
if (buf[i] != padding_hash[i]) {
return 0;
}
}

View file

@ -1,6 +1,6 @@
/* sha.c
**
** Copyright 2008, The Android Open Source Project
** Copyright 2013, The Android Open Source Project
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
@ -25,177 +25,20 @@
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Optimized for minimal code size.
#include "mincrypt/sha.h"
// Some machines lack byteswap.h and endian.h. These have to use the
// slower code, even if they're little-endian.
#if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN)
#include <byteswap.h>
#include <memory.h>
// This version is about 28% faster than the generic version below,
// but assumes little-endianness.
static inline uint32_t ror27(uint32_t val) {
return (val >> 27) | (val << 5);
}
static inline uint32_t ror2(uint32_t val) {
return (val >> 2) | (val << 30);
}
static inline uint32_t ror31(uint32_t val) {
return (val >> 31) | (val << 1);
}
static void SHA1_Transform(SHA_CTX* ctx) {
uint32_t W[80];
register uint32_t A, B, C, D, E;
int t;
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
#define SHA_F1(A,B,C,D,E,t) \
E += ror27(A) + \
(W[t] = bswap_32(ctx->buf.w[t])) + \
(D^(B&(C^D))) + 0x5A827999; \
B = ror2(B);
for (t = 0; t < 15; t += 5) {
SHA_F1(A,B,C,D,E,t + 0);
SHA_F1(E,A,B,C,D,t + 1);
SHA_F1(D,E,A,B,C,t + 2);
SHA_F1(C,D,E,A,B,t + 3);
SHA_F1(B,C,D,E,A,t + 4);
}
SHA_F1(A,B,C,D,E,t + 0); // 16th one, t == 15
#undef SHA_F1
#define SHA_F1(A,B,C,D,E,t) \
E += ror27(A) + \
(W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \
(D^(B&(C^D))) + 0x5A827999; \
B = ror2(B);
SHA_F1(E,A,B,C,D,t + 1);
SHA_F1(D,E,A,B,C,t + 2);
SHA_F1(C,D,E,A,B,t + 3);
SHA_F1(B,C,D,E,A,t + 4);
#undef SHA_F1
#define SHA_F2(A,B,C,D,E,t) \
E += ror27(A) + \
(W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \
(B^C^D) + 0x6ED9EBA1; \
B = ror2(B);
for (t = 20; t < 40; t += 5) {
SHA_F2(A,B,C,D,E,t + 0);
SHA_F2(E,A,B,C,D,t + 1);
SHA_F2(D,E,A,B,C,t + 2);
SHA_F2(C,D,E,A,B,t + 3);
SHA_F2(B,C,D,E,A,t + 4);
}
#undef SHA_F2
#define SHA_F3(A,B,C,D,E,t) \
E += ror27(A) + \
(W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \
((B&C)|(D&(B|C))) + 0x8F1BBCDC; \
B = ror2(B);
for (; t < 60; t += 5) {
SHA_F3(A,B,C,D,E,t + 0);
SHA_F3(E,A,B,C,D,t + 1);
SHA_F3(D,E,A,B,C,t + 2);
SHA_F3(C,D,E,A,B,t + 3);
SHA_F3(B,C,D,E,A,t + 4);
}
#undef SHA_F3
#define SHA_F4(A,B,C,D,E,t) \
E += ror27(A) + \
(W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \
(B^C^D) + 0xCA62C1D6; \
B = ror2(B);
for (; t < 80; t += 5) {
SHA_F4(A,B,C,D,E,t + 0);
SHA_F4(E,A,B,C,D,t + 1);
SHA_F4(D,E,A,B,C,t + 2);
SHA_F4(C,D,E,A,B,t + 3);
SHA_F4(B,C,D,E,A,t + 4);
}
#undef SHA_F4
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
}
void SHA_update(SHA_CTX* ctx, const void* data, int len) {
int i = ctx->count % sizeof(ctx->buf);
const uint8_t* p = (const uint8_t*)data;
ctx->count += len;
while (len > sizeof(ctx->buf) - i) {
memcpy(&ctx->buf.b[i], p, sizeof(ctx->buf) - i);
len -= sizeof(ctx->buf) - i;
p += sizeof(ctx->buf) - i;
SHA1_Transform(ctx);
i = 0;
}
while (len--) {
ctx->buf.b[i++] = *p++;
if (i == sizeof(ctx->buf)) {
SHA1_Transform(ctx);
i = 0;
}
}
}
const uint8_t* SHA_final(SHA_CTX* ctx) {
uint64_t cnt = ctx->count * 8;
int i;
SHA_update(ctx, (uint8_t*)"\x80", 1);
while ((ctx->count % sizeof(ctx->buf)) != (sizeof(ctx->buf) - 8)) {
SHA_update(ctx, (uint8_t*)"\0", 1);
}
for (i = 0; i < 8; ++i) {
uint8_t tmp = cnt >> ((7 - i) * 8);
SHA_update(ctx, &tmp, 1);
}
for (i = 0; i < 5; i++) {
ctx->buf.w[i] = bswap_32(ctx->state[i]);
}
return ctx->buf.b;
}
#else // #if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN)
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits))))
static void SHA1_transform(SHA_CTX *ctx) {
static void SHA1_Transform(SHA_CTX* ctx) {
uint32_t W[80];
uint32_t A, B, C, D, E;
uint8_t *p = ctx->buf;
uint8_t* p = ctx->buf;
int t;
for(t = 0; t < 16; ++t) {
@ -242,31 +85,52 @@ static void SHA1_transform(SHA_CTX *ctx) {
ctx->state[4] += E;
}
void SHA_update(SHA_CTX *ctx, const void *data, int len) {
int i = ctx->count % sizeof(ctx->buf);
static const HASH_VTAB SHA_VTAB = {
SHA_init,
SHA_update,
SHA_final,
SHA_hash,
SHA_DIGEST_SIZE
};
void SHA_init(SHA_CTX* ctx) {
ctx->f = &SHA_VTAB;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
ctx->state[4] = 0xC3D2E1F0;
ctx->count = 0;
}
void SHA_update(SHA_CTX* ctx, const void* data, int len) {
int i = (int) (ctx->count & 63);
const uint8_t* p = (const uint8_t*)data;
ctx->count += len;
while (len--) {
ctx->buf[i++] = *p++;
if (i == sizeof(ctx->buf)) {
SHA1_transform(ctx);
if (i == 64) {
SHA1_Transform(ctx);
i = 0;
}
}
}
const uint8_t *SHA_final(SHA_CTX *ctx) {
const uint8_t* SHA_final(SHA_CTX* ctx) {
uint8_t *p = ctx->buf;
uint64_t cnt = ctx->count * 8;
int i;
SHA_update(ctx, (uint8_t*)"\x80", 1);
while ((ctx->count % sizeof(ctx->buf)) != (sizeof(ctx->buf) - 8)) {
while ((ctx->count & 63) != 56) {
SHA_update(ctx, (uint8_t*)"\0", 1);
}
for (i = 0; i < 8; ++i) {
uint8_t tmp = cnt >> ((7 - i) * 8);
uint8_t tmp = (uint8_t) (cnt >> ((7 - i) * 8));
SHA_update(ctx, &tmp, 1);
}
@ -281,27 +145,11 @@ const uint8_t *SHA_final(SHA_CTX *ctx) {
return ctx->buf;
}
#endif // endianness
void SHA_init(SHA_CTX* ctx) {
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
ctx->state[4] = 0xC3D2E1F0;
ctx->count = 0;
}
/* Convenience function */
const uint8_t* SHA(const void *data, int len, uint8_t *digest) {
const uint8_t *p;
int i;
const uint8_t* SHA_hash(const void* data, int len, uint8_t* digest) {
SHA_CTX ctx;
SHA_init(&ctx);
SHA_update(&ctx, data, len);
p = SHA_final(&ctx);
for (i = 0; i < SHA_DIGEST_SIZE; ++i) {
digest[i] = *p++;
}
memcpy(digest, SHA_final(&ctx), SHA_DIGEST_SIZE);
return digest;
}

184
libmincrypt/sha256.c Normal file
View file

@ -0,0 +1,184 @@
/* sha256.c
**
** Copyright 2013, The Android Open Source Project
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of Google Inc. nor the names of its contributors may
** be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Optimized for minimal code size.
#include "mincrypt/sha256.h"
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define ror(value, bits) (((value) >> (bits)) | ((value) << (32 - (bits))))
#define shr(value, bits) ((value) >> (bits))
static const uint32_t K[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 };
static void SHA256_Transform(SHA256_CTX* ctx) {
uint32_t W[64];
uint32_t A, B, C, D, E, F, G, H;
uint8_t* p = ctx->buf;
int t;
for(t = 0; t < 16; ++t) {
uint32_t tmp = *p++ << 24;
tmp |= *p++ << 16;
tmp |= *p++ << 8;
tmp |= *p++;
W[t] = tmp;
}
for(; t < 64; t++) {
uint32_t s0 = ror(W[t-15], 7) ^ ror(W[t-15], 18) ^ shr(W[t-15], 3);
uint32_t s1 = ror(W[t-2], 17) ^ ror(W[t-2], 19) ^ shr(W[t-2], 10);
W[t] = W[t-16] + s0 + W[t-7] + s1;
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
F = ctx->state[5];
G = ctx->state[6];
H = ctx->state[7];
for(t = 0; t < 64; t++) {
uint32_t s0 = ror(A, 2) ^ ror(A, 13) ^ ror(A, 22);
uint32_t maj = (A & B) ^ (A & C) ^ (B & C);
uint32_t t2 = s0 + maj;
uint32_t s1 = ror(E, 6) ^ ror(E, 11) ^ ror(E, 25);
uint32_t ch = (E & F) ^ ((~E) & G);
uint32_t t1 = H + s1 + ch + K[t] + W[t];
H = G;
G = F;
F = E;
E = D + t1;
D = C;
C = B;
B = A;
A = t1 + t2;
}
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
ctx->state[5] += F;
ctx->state[6] += G;
ctx->state[7] += H;
}
static const HASH_VTAB SHA256_VTAB = {
SHA256_init,
SHA256_update,
SHA256_final,
SHA256_hash,
SHA256_DIGEST_SIZE
};
void SHA256_init(SHA256_CTX* ctx) {
ctx->f = &SHA256_VTAB;
ctx->state[0] = 0x6a09e667;
ctx->state[1] = 0xbb67ae85;
ctx->state[2] = 0x3c6ef372;
ctx->state[3] = 0xa54ff53a;
ctx->state[4] = 0x510e527f;
ctx->state[5] = 0x9b05688c;
ctx->state[6] = 0x1f83d9ab;
ctx->state[7] = 0x5be0cd19;
ctx->count = 0;
}
void SHA256_update(SHA256_CTX* ctx, const void* data, int len) {
int i = (int) (ctx->count & 63);
const uint8_t* p = (const uint8_t*)data;
ctx->count += len;
while (len--) {
ctx->buf[i++] = *p++;
if (i == 64) {
SHA256_Transform(ctx);
i = 0;
}
}
}
const uint8_t* SHA256_final(SHA256_CTX* ctx) {
uint8_t *p = ctx->buf;
uint64_t cnt = ctx->count * 8;
int i;
SHA256_update(ctx, (uint8_t*)"\x80", 1);
while ((ctx->count & 63) != 56) {
SHA256_update(ctx, (uint8_t*)"\0", 1);
}
for (i = 0; i < 8; ++i) {
uint8_t tmp = (uint8_t) (cnt >> ((7 - i) * 8));
SHA256_update(ctx, &tmp, 1);
}
for (i = 0; i < 8; i++) {
uint32_t tmp = ctx->state[i];
*p++ = tmp >> 24;
*p++ = tmp >> 16;
*p++ = tmp >> 8;
*p++ = tmp >> 0;
}
return ctx->buf;
}
/* Convenience function */
const uint8_t* SHA256_hash(const void* data, int len, uint8_t* digest) {
SHA256_CTX ctx;
SHA256_init(&ctx);
SHA256_update(&ctx, data, len);
memcpy(digest, SHA256_final(&ctx), SHA256_DIGEST_SIZE);
return digest;
}

View file

@ -19,7 +19,7 @@ package com.android.dumpkey;
import java.io.FileInputStream;
import java.math.BigInteger;
import java.security.cert.CertificateFactory;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.security.KeyStore;
import java.security.Key;
import java.security.PublicKey;
@ -34,20 +34,22 @@ class DumpPublicKey {
/**
* @param key to perform sanity checks on
* @return version number of key. Supported versions are:
* 1: 2048-bit key with e=3
* 2: 2048-bit key with e=65537
* 1: 2048-bit RSA key with e=3 and SHA-1 hash
* 2: 2048-bit RSA key with e=65537 and SHA-1 hash
* 3: 2048-bit RSA key with e=3 and SHA-256 hash
* 4: 2048-bit RSA key with e=65537 and SHA-256 hash
* @throws Exception if the key has the wrong size or public exponent
*/
static int check(RSAPublicKey key) throws Exception {
static int check(RSAPublicKey key, boolean useSHA256) throws Exception {
BigInteger pubexp = key.getPublicExponent();
BigInteger modulus = key.getModulus();
int version;
if (pubexp.equals(BigInteger.valueOf(3))) {
version = 1;
version = useSHA256 ? 3 : 1;
} else if (pubexp.equals(BigInteger.valueOf(65537))) {
version = 2;
version = useSHA256 ? 4 : 2;
} else {
throw new Exception("Public exponent should be 3 or 65537 but is " +
pubexp.toString(10) + ".");
@ -67,8 +69,8 @@ class DumpPublicKey {
* version 1 key, the string will be a C initializer; this is
* not true for newer key versions.
*/
static String print(RSAPublicKey key) throws Exception {
int version = check(key);
static String print(RSAPublicKey key, boolean useSHA256) throws Exception {
int version = check(key, useSHA256);
BigInteger N = key.getModulus();
@ -135,10 +137,27 @@ class DumpPublicKey {
for (int i = 0; i < args.length; i++) {
FileInputStream input = new FileInputStream(args[i]);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate cert = cf.generateCertificate(input);
X509Certificate cert = (X509Certificate) cf.generateCertificate(input);
boolean useSHA256 = false;
String sigAlg = cert.getSigAlgName();
if ("SHA1withRSA".equals(sigAlg) || "MD5withRSA".equals(sigAlg)) {
// SignApk has historically accepted "MD5withRSA"
// certificates, but treated them as "SHA1withRSA"
// anyway. Continue to do so for backwards
// compatibility.
useSHA256 = false;
} else if ("SHA256withRSA".equals(sigAlg)) {
useSHA256 = true;
} else {
System.err.println(args[i] + ": unsupported signature algorithm \"" +
sigAlg + "\"");
System.exit(1);
}
RSAPublicKey key = (RSAPublicKey) (cert.getPublicKey());
check(key);
System.out.print(print(key));
check(key, useSHA256);
System.out.print(print(key, useSHA256));
System.out.println(i < args.length - 1 ? "," : "");
}
} catch (Exception e) {