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:
parent
5cad711976
commit
515e1639ef
12 changed files with 465 additions and 268 deletions
|
@ -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;
|
||||
}
|
||||
|
|
40
include/mincrypt/hash-internal.h
Normal file
40
include/mincrypt/hash-internal.h
Normal 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__
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
29
include/mincrypt/sha256.h
Normal 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__
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
184
libmincrypt/sha256.c
Normal 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;
|
||||
}
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue