M7350v1_en_gpl

This commit is contained in:
T
2024-09-09 08:52:07 +00:00
commit f9cc65cfda
65988 changed files with 26357421 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
# Copyright 2008 The Android Open Source Project
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libmincrypt
LOCAL_SRC_FILES := rsa.c sha.c
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libmincrypt
LOCAL_SRC_FILES := rsa.c sha.c
include $(BUILD_HOST_STATIC_LIBRARY)
# TODO: drop the hyphen once these are checked in
include $(LOCAL_PATH)/tools/Android.mk

View File

@@ -0,0 +1,28 @@
AM_CFLAGS := -Wundef \
-Wstrict-prototypes \
-Wno-trigraphs \
-g -O0 \
-fno-inline \
-fno-short-enums \
-fpic
AM_CPPFLAGS := \
-I. \
-I$(WORKSPACE)/system/core/include
AM_LDFLAGS := -shared -version-info 1:0:0
c_sources := rsa.c sha.c
library_includedir := $(pkgincludedir)
library_include_HEADERS := $(h_sources)
lib_LTLIBRARIES := libmincrypt.la
libmincrypt_la_SOURCES := $(c_sources) $(h_sources)
libmincrypt_la_CFLAGS := $(AM_CFLAGS) -DUSE_GLIB
libmincrypt_la_CPPFLAGS := $(AM_CPPFLAGS) -DUSE_GLIB
libmincrypt_la_LIBADD := -lm -lpthread
libmincrypt_la_LDFLAGS := -all-static
pkgconfigdir := $(libdir)/pkgconfig
pkgconfig_DATA := libmincrypt.pc
EXTRA_DIST := $(pkgconfig_DATA)

View File

@@ -0,0 +1,23 @@
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.

View File

@@ -0,0 +1,10 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: mincrypt
Description: Mincrypt library
Version: @VERSION@
Libs: -L${libdir} -lmincrypt
Cflags: -I${includedir}

View File

@@ -0,0 +1,198 @@
/* rsa.c
**
** 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.
*/
#include "mincrypt/rsa.h"
#include "mincrypt/sha.h"
/* a[] -= mod */
static void subM(const RSAPublicKey *key, uint32_t *a) {
int64_t A = 0;
int i;
for (i = 0; i < key->len; ++i) {
A += (uint64_t)a[i] - key->n[i];
a[i] = (uint32_t)A;
A >>= 32;
}
}
/* return a[] >= mod */
static int geM(const RSAPublicKey *key, const uint32_t *a) {
int i;
for (i = key->len; i;) {
--i;
if (a[i] < key->n[i]) return 0;
if (a[i] > key->n[i]) return 1;
}
return 1; /* equal */
}
/* montgomery c[] += a * b[] / R % mod */
static void montMulAdd(const RSAPublicKey *key,
uint32_t* c,
const uint32_t a,
const uint32_t* b) {
uint64_t A = (uint64_t)a * b[0] + c[0];
uint32_t d0 = (uint32_t)A * key->n0inv;
uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A;
int i;
for (i = 1; i < key->len; ++i) {
A = (A >> 32) + (uint64_t)a * b[i] + c[i];
B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A;
c[i - 1] = (uint32_t)B;
}
A = (A >> 32) + (B >> 32);
c[i - 1] = (uint32_t)A;
if (A >> 32) {
subM(key, c);
}
}
/* montgomery c[] = a[] * b[] / R % mod */
static void montMul(const RSAPublicKey *key,
uint32_t* c,
const uint32_t* a,
const uint32_t* b) {
int i;
for (i = 0; i < key->len; ++i) {
c[i] = 0;
}
for (i = 0; i < key->len; ++i) {
montMulAdd(key, c, a[i], b);
}
}
/* In-place public exponentiation.
** Input and output big-endian byte array in inout.
*/
static void modpow3(const RSAPublicKey *key,
uint8_t* inout) {
uint32_t a[RSANUMWORDS];
uint32_t aR[RSANUMWORDS];
uint32_t aaR[RSANUMWORDS];
uint32_t *aaa = aR; /* Re-use location. */
int i;
/* Convert from big endian byte array to little endian word array. */
for (i = 0; i < key->len; ++i) {
uint32_t tmp =
(inout[((key->len - 1 - i) * 4) + 0] << 24) |
(inout[((key->len - 1 - i) * 4) + 1] << 16) |
(inout[((key->len - 1 - i) * 4) + 2] << 8) |
(inout[((key->len - 1 - i) * 4) + 3] << 0);
a[i] = tmp;
}
montMul(key, aR, a, key->rr); /* aR = a * RR / R mod M */
montMul(key, aaR, aR, aR); /* aaR = aR * aR / R mod M */
montMul(key, aaa, aaR, a); /* aaa = aaR * a / R mod M */
/* Make sure aaa < mod; aaa is at most 1x mod too large. */
if (geM(key, aaa)) {
subM(key, aaa);
}
/* Convert to bigendian byte array */
for (i = key->len - 1; i >= 0; --i) {
uint32_t tmp = aaa[i];
*inout++ = tmp >> 24;
*inout++ = tmp >> 16;
*inout++ = tmp >> 8;
*inout++ = tmp >> 0;
}
}
/* Expected PKCS1.5 signature padding bytes, for a keytool RSA signature.
** Has the 0-length optional parameter encoded in the ASN1 (as opposed to the
** 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] = {
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
};
/* Verify a 2048 bit RSA PKCS1.5 signature against an expected SHA-1 hash.
** Returns 0 on failure, 1 on success.
*/
int RSA_verify(const RSAPublicKey *key,
const uint8_t *signature,
const int len,
const uint8_t *sha) {
uint8_t buf[RSANUMBYTES];
int i;
if (key->len != RSANUMWORDS) {
return 0; /* Wrong key passed in. */
}
if (len != sizeof(buf)) {
return 0; /* Wrong input length. */
}
for (i = 0; i < len; ++i) {
buf[i] = signature[i];
}
modpow3(key, buf);
/* Check pkcs1.5 padding bytes. */
for (i = 0; i < (int) sizeof(padding); ++i) {
if (buf[i] != padding[i]) {
return 0;
}
}
/* Check sha digest matches. */
for (; i < len; ++i) {
if (buf[i] != *sha++) {
return 0;
}
}
return 1;
}

View File

@@ -0,0 +1,307 @@
/* sha.c
**
** 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.
*/
#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)
#define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits))))
static void SHA1_transform(SHA_CTX *ctx) {
uint32_t W[80];
uint32_t A, B, C, D, E;
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 < 80; t++) {
W[t] = rol(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
for(t = 0; t < 80; t++) {
uint32_t tmp = rol(5,A) + E + W[t];
if (t < 20)
tmp += (D^(B&(C^D))) + 0x5A827999;
else if ( t < 40)
tmp += (B^C^D) + 0x6ED9EBA1;
else if ( t < 60)
tmp += ((B&C)|(D&(B|C))) + 0x8F1BBCDC;
else
tmp += (B^C^D) + 0xCA62C1D6;
E = D;
D = C;
C = rol(30,B);
B = A;
A = tmp;
}
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--) {
ctx->buf[i++] = *p++;
if (i == sizeof(ctx->buf)) {
SHA1_transform(ctx);
i = 0;
}
}
}
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)) {
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++) {
uint32_t tmp = ctx->state[i];
*p++ = tmp >> 24;
*p++ = tmp >> 16;
*p++ = tmp >> 8;
*p++ = tmp >> 0;
}
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;
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++;
}
return digest;
}

View File

@@ -0,0 +1,21 @@
# Copyright (C) 2008 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := dumpkey
LOCAL_SRC_FILES := DumpPublicKey.java
LOCAL_JAR_MANIFEST := DumpPublicKey.mf
include $(BUILD_HOST_JAVA_LIBRARY)

View File

@@ -0,0 +1,130 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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.KeyStore;
import java.security.Key;
import java.security.PublicKey;
import java.security.interfaces.RSAPublicKey;
import sun.misc.BASE64Encoder;
/**
* Command line tool to extract RSA public keys from X.509 certificates
* and output source code with data initializers for the keys.
* @hide
*/
class DumpPublicKey {
/**
* @param key to perform sanity checks on
* @throws Exception if the key has the wrong size or public exponent
*/
static void check(RSAPublicKey key) throws Exception {
BigInteger pubexp = key.getPublicExponent();
BigInteger modulus = key.getModulus();
if (!pubexp.equals(BigInteger.valueOf(3)))
throw new Exception("Public exponent should be 3 but is " +
pubexp.toString(10) + ".");
if (modulus.bitLength() != 2048)
throw new Exception("Modulus should be 2048 bits long but is " +
modulus.bitLength() + " bits.");
}
/**
* @param key to output
* @return a C initializer representing this public key.
*/
static String print(RSAPublicKey key) throws Exception {
check(key);
BigInteger N = key.getModulus();
StringBuilder result = new StringBuilder();
int nwords = N.bitLength() / 32; // # of 32 bit integers in modulus
result.append("{");
result.append(nwords);
BigInteger B = BigInteger.valueOf(0x100000000L); // 2^32
BigInteger N0inv = B.subtract(N.modInverse(B)); // -1 / N[0] mod 2^32
result.append(",0x");
result.append(N0inv.toString(16));
BigInteger R = BigInteger.valueOf(2).pow(N.bitLength());
BigInteger RR = R.multiply(R).mod(N); // 2^4096 mod N
// Write out modulus as little endian array of integers.
result.append(",{");
for (int i = 0; i < nwords; ++i) {
long n = N.mod(B).longValue();
result.append(n);
if (i != nwords - 1) {
result.append(",");
}
N = N.divide(B);
}
result.append("}");
// Write R^2 as little endian array of integers.
result.append(",{");
for (int i = 0; i < nwords; ++i) {
long rr = RR.mod(B).longValue();
result.append(rr);
if (i != nwords - 1) {
result.append(",");
}
RR = RR.divide(B);
}
result.append("}");
result.append("}");
return result.toString();
}
public static void main(String[] args) {
if (args.length < 1) {
System.err.println("Usage: DumpPublicKey certfile ... > source.c");
System.exit(1);
}
try {
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);
RSAPublicKey key = (RSAPublicKey) (cert.getPublicKey());
check(key);
System.out.print(print(key));
System.out.println(i < args.length - 1 ? "," : "");
}
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
System.exit(0);
}
}

View File

@@ -0,0 +1 @@
Main-Class: com.android.dumpkey.DumpPublicKey