first and last commit

This commit is contained in:
Chris Nutter committed 2023-07-08 13:03:17 -07:00
commit 1bf4efd552
2612 files changed
+636500

No files matched your search

+102
View File
@@ -0,0 +1,102 @@
/*
* Copyright (C) 2007 Apple Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#ifndef __APPLE_CA_H
#define __APPLE_CA_H
#if PKI_CHECK_ANCHOR_BY_SHA1
static const unsigned char ROOT_CA_SHA1_HASH[20] = {
0x61, 0x1E, 0x5B, 0x66, 0x2C, 0x59, 0x3A, 0x08, 0xFF, 0x58,
0xD1, 0x4A, 0xE2, 0x24, 0x52, 0xD1, 0x98, 0xDF, 0x6C, 0x60 };
#else
static const unsigned char ROOT_CA_CERTIFICATE[1215] = {
0x30,0x82,0x04,0xBB,0x30,0x82,0x03,0xA3,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x02,
0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,
0x62,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,
0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,
0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,0x1D,0x41,0x70,
0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,
0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x16,0x30,0x14,0x06,
0x03,0x55,0x04,0x03,0x13,0x0D,0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,
0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x30,0x36,0x30,0x34,0x32,0x35,0x32,0x31,0x34,
0x30,0x33,0x36,0x5A,0x17,0x0D,0x33,0x35,0x30,0x32,0x30,0x39,0x32,0x31,0x34,0x30,
0x33,0x36,0x5A,0x30,0x62,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,
0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,
0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,
0x13,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,
0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,
0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x03,0x13,0x0D,0x41,0x70,0x70,0x6C,0x65,0x20,
0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,
0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,
0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xE4,0x91,0xA9,0x09,0x1F,0x91,0xDB,0x1E,
0x47,0x50,0xEB,0x05,0xED,0x5E,0x79,0x84,0x2D,0xEB,0x36,0xA2,0x57,0x4C,0x55,0xEC,
0x8B,0x19,0x89,0xDE,0xF9,0x4B,0x6C,0xF5,0x07,0xAB,0x22,0x30,0x02,0xE8,0x18,0x3E,
0xF8,0x50,0x09,0xD3,0x7F,0x41,0xA8,0x98,0xF9,0xD1,0xCA,0x66,0x9C,0x24,0x6B,0x11,
0xD0,0xA3,0xBB,0xE4,0x1B,0x2A,0xC3,0x1F,0x95,0x9E,0x7A,0x0C,0xA4,0x47,0x8B,0x5B,
0xD4,0x16,0x37,0x33,0xCB,0xC4,0x0F,0x4D,0xCE,0x14,0x69,0xD1,0xC9,0x19,0x72,0xF5,
0x5D,0x0E,0xD5,0x7F,0x5F,0x9B,0xF2,0x25,0x03,0xBA,0x55,0x8F,0x4D,0x5D,0x0D,0xF1,
0x64,0x35,0x23,0x15,0x4B,0x15,0x59,0x1D,0xB3,0x94,0xF7,0xF6,0x9C,0x9E,0xCF,0x50,
0xBA,0xC1,0x58,0x50,0x67,0x8F,0x08,0xB4,0x20,0xF7,0xCB,0xAC,0x2C,0x20,0x6F,0x70,
0xB6,0x3F,0x01,0x30,0x8C,0xB7,0x43,0xCF,0x0F,0x9D,0x3D,0xF3,0x2B,0x49,0x28,0x1A,
0xC8,0xFE,0xCE,0xB5,0xB9,0x0E,0xD9,0x5E,0x1C,0xD6,0xCB,0x3D,0xB5,0x3A,0xAD,0xF4,
0x0F,0x0E,0x00,0x92,0x0B,0xB1,0x21,0x16,0x2E,0x74,0xD5,0x3C,0x0D,0xDB,0x62,0x16,
0xAB,0xA3,0x71,0x92,0x47,0x53,0x55,0xC1,0xAF,0x2F,0x41,0xB3,0xF8,0xFB,0xE3,0x70,
0xCD,0xE6,0xA3,0x4C,0x45,0x7E,0x1F,0x4C,0x6B,0x50,0x96,0x41,0x89,0xC4,0x74,0x62,
0x0B,0x10,0x83,0x41,0x87,0x33,0x8A,0x81,0xB1,0x30,0x58,0xEC,0x5A,0x04,0x32,0x8C,
0x68,0xB3,0x8F,0x1D,0xDE,0x65,0x73,0xFF,0x67,0x5E,0x65,0xBC,0x49,0xD8,0x76,0x9F,
0x33,0x14,0x65,0xA1,0x77,0x94,0xC9,0x2D,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x01,
0x7A,0x30,0x82,0x01,0x76,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,
0x04,0x03,0x02,0x01,0x06,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,
0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,
0x14,0x2B,0xD0,0x69,0x47,0x94,0x76,0x09,0xFE,0xF4,0x6B,0x8D,0x2E,0x40,0xA6,0xF7,
0x47,0x4D,0x7F,0x08,0x5E,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,
0x80,0x14,0x2B,0xD0,0x69,0x47,0x94,0x76,0x09,0xFE,0xF4,0x6B,0x8D,0x2E,0x40,0xA6,
0xF7,0x47,0x4D,0x7F,0x08,0x5E,0x30,0x82,0x01,0x11,0x06,0x03,0x55,0x1D,0x20,0x04,
0x82,0x01,0x08,0x30,0x82,0x01,0x04,0x30,0x82,0x01,0x00,0x06,0x09,0x2A,0x86,0x48,
0x86,0xF7,0x63,0x64,0x05,0x01,0x30,0x81,0xF2,0x30,0x2A,0x06,0x08,0x2B,0x06,0x01,
0x05,0x05,0x07,0x02,0x01,0x16,0x1E,0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x77,
0x77,0x77,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x61,0x70,0x70,
0x6C,0x65,0x63,0x61,0x2F,0x30,0x81,0xC3,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,
0x02,0x02,0x30,0x81,0xB6,0x1A,0x81,0xB3,0x52,0x65,0x6C,0x69,0x61,0x6E,0x63,0x65,
0x20,0x6F,0x6E,0x20,0x74,0x68,0x69,0x73,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69,
0x63,0x61,0x74,0x65,0x20,0x62,0x79,0x20,0x61,0x6E,0x79,0x20,0x70,0x61,0x72,0x74,
0x79,0x20,0x61,0x73,0x73,0x75,0x6D,0x65,0x73,0x20,0x61,0x63,0x63,0x65,0x70,0x74,
0x61,0x6E,0x63,0x65,0x20,0x6F,0x66,0x20,0x74,0x68,0x65,0x20,0x74,0x68,0x65,0x6E,
0x20,0x61,0x70,0x70,0x6C,0x69,0x63,0x61,0x62,0x6C,0x65,0x20,0x73,0x74,0x61,0x6E,
0x64,0x61,0x72,0x64,0x20,0x74,0x65,0x72,0x6D,0x73,0x20,0x61,0x6E,0x64,0x20,0x63,
0x6F,0x6E,0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x20,0x6F,0x66,0x20,0x75,0x73,0x65,
0x2C,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x20,0x70,0x6F,
0x6C,0x69,0x63,0x79,0x20,0x61,0x6E,0x64,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69,
0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x70,0x72,0x61,0x63,0x74,0x69,0x63,0x65,0x20,
0x73,0x74,0x61,0x74,0x65,0x6D,0x65,0x6E,0x74,0x73,0x2E,0x30,0x0D,0x06,0x09,0x2A,
0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x5C,
0x36,0x99,0x4C,0x2D,0x78,0xB7,0xED,0x8C,0x9B,0xDC,0xF3,0x77,0x9B,0xF2,0x76,0xD2,
0x77,0x30,0x4F,0xC1,0x1F,0x85,0x83,0x85,0x1B,0x99,0x3D,0x47,0x37,0xF2,0xA9,0x9B,
0x40,0x8E,0x2C,0xD4,0xB1,0x90,0x12,0xD8,0xBE,0xF4,0x73,0x9B,0xEE,0xD2,0x64,0x0F,
0xCB,0x79,0x4F,0x34,0xD8,0xA2,0x3E,0xF9,0x78,0xFF,0x6B,0xC8,0x07,0xEC,0x7D,0x39,
0x83,0x8B,0x53,0x20,0xD3,0x38,0xC4,0xB1,0xBF,0x9A,0x4F,0x0A,0x6B,0xFF,0x2B,0xFC,
0x59,0xA7,0x05,0x09,0x7C,0x17,0x40,0x56,0x11,0x1E,0x74,0xD3,0xB7,0x8B,0x23,0x3B,
0x47,0xA3,0xD5,0x6F,0x24,0xE2,0xEB,0xD1,0xB7,0x70,0xDF,0x0F,0x45,0xE1,0x27,0xCA,
0xF1,0x6D,0x78,0xED,0xE7,0xB5,0x17,0x17,0xA8,0xDC,0x7E,0x22,0x35,0xCA,0x25,0xD5,
0xD9,0x0F,0xD6,0x6B,0xD4,0xA2,0x24,0x23,0x11,0xF7,0xA1,0xAC,0x8F,0x73,0x81,0x60,
0xC6,0x1B,0x5B,0x09,0x2F,0x92,0xB2,0xF8,0x44,0x48,0xF0,0x60,0x38,0x9E,0x15,0xF5,
0x3D,0x26,0x67,0x20,0x8A,0x33,0x6A,0xF7,0x0D,0x82,0xCF,0xDE,0xEB,0xA3,0x2F,0xF9,
0x53,0x6A,0x5B,0x64,0xC0,0x63,0x33,0x77,0xF7,0x3A,0x07,0x2C,0x56,0xEB,0xDA,0x0F,
0x21,0x0E,0xDA,0xBA,0x73,0x19,0x4F,0xB5,0xD9,0x36,0x7F,0xC1,0x87,0x55,0xD9,0xA7,
0x99,0xB9,0x32,0x42,0xFB,0xD8,0xD5,0x71,0x9E,0x7E,0xA1,0x52,0xB7,0x1B,0xBD,0x93,
0x42,0x24,0x12,0x2A,0xC7,0x0F,0x1D,0xB6,0x4D,0x9C,0x5E,0x63,0xC8,0x4B,0x80,0x17,
0x50,0xAA,0x8A,0xD5,0xDA,0xE4,0xFC,0xD0,0x09,0x07,0x37,0xB0,0x75,0x75,0x21,
};
#endif /* PKI_CHECK_ANCHOR_BY_SHA1 */
#endif /* __APPLE_CA_H */
+662
View File
@@ -0,0 +1,662 @@
/*
* Copyright (C) 2007-2008 Apple Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#include <platform.h>
#include <libDER/DER_CertCrl.h>
#include <libDER/DER_Keys.h>
#include <libDER/DER_Digest.h>
#include <libDER/oids.h>
#include <libDER/asn1Types.h>
#ifndef WITH_HW_PKE
#include <libgRSA/libgRSA.h>
#include <libgRSA/libgRSA_DER.h>
#include <libgRSA/libgRSA_priv.h>
#include <libGiants/giantDebug.h>
#endif
#include <debug.h>
#if DEBUG_BUILD
#ifndef DEBUG_ASSERT_PRODUCTION_CODE
#define DEBUG_ASSERT_PRODUCTION_CODE 0
#endif
#endif
#include <AssertMacros.h>
#include <drivers/pke.h>
#include <drivers/sha1.h>
#include <lib/pki.h>
#if PKI_APPLE_ROOT_CA
#include <apple_ca.h>
#else
#include <fake_ca.h>
#endif
typedef struct {
DERItem subjectKeyID;
DERItem authorityKeyID;
DERItem appleSpecBlob;
DERItem appleSpecTicketBlob;
} DERExtensions;
static int extension_octet_string_value(DERExtension *extn, bool critical,
DERItem *value)
{
DERDecodedInfo extn_info;
#if 0
if (critical) {
/* this is more important to be enforced when issued */
bool critical;
require_noerr(DERParseBoolean(&extn->critical, false, &critical), out);
require(critical, out);
}
#endif
/* get value */
require_noerr(DERDecodeItem(&extn->extnValue, &extn_info), out);
require(extn_info.tag == ASN1_OCTET_STRING, out);
*value = extn_info.content;
return 0;
out:
return -1;
}
static int extension_sequence_item(DERExtension *extn, bool critical,
DERItem *value)
{
DERDecodedInfo extn_info;
#if 0
if (critical) {
/* this is more important to be enforced when issued */
bool critical;
require_noerr(DERParseBoolean(&extn->critical, false, &critical), out);
require(critical, out);
}
#endif
/* get the sequence */
require_noerr(DERDecodeItem(&extn->extnValue, &extn_info), out);
require(extn_info.tag == ASN1_CONSTR_SEQUENCE, out);
*value = extn->extnValue;
return 0;
out:
return -1;
}
/**
* Find extension with oidAppleSecureBootCertSpec oid and return octet string.
* It's not an error to not find it, but general parse errors are flagged.
*/
static int parse_extensions(DERTBSCert *tbsCert, DERExtensions *extensions)
{
DERSequence derSeq;
DERTag tag;
DERDecodedInfo currDecoded;
DERExtension extn;
bzero(extensions, sizeof(*extensions));
if (tbsCert->extensions.length) {
require_noerr(DERDecodeSeqInit(&tbsCert->extensions, &tag, &derSeq), out);
require(tag == ASN1_CONSTR_SEQUENCE, out);
while (DERDecodeSeqNext(&derSeq, &currDecoded) == DR_Success) {
require(currDecoded.tag == ASN1_CONSTR_SEQUENCE, out);
require_noerr(DERParseSequenceContent(&currDecoded.content,
DERNumExtensionItemSpecs, DERExtensionItemSpecs,
&extn, sizeof(extn)), out);
if (DEROidCompare(&oidAppleSecureBootTicketCertSpec, &extn.extnID)) {
require_noerr(extension_sequence_item(&extn, false,
&extensions->appleSpecTicketBlob), out);
dprintf(DEBUG_SPEW, "found apple spec (ticket) extension (%p, %u)\n",
extensions->appleSpecTicketBlob.data,
extensions->appleSpecTicketBlob.length);
}
else if (DEROidCompare(&oidAppleSecureBootCertSpec, &extn.extnID)) {
require_noerr(extension_octet_string_value(&extn, false,
&extensions->appleSpecBlob), out);
dprintf(DEBUG_SPEW, "found apple spec (image3) extension (%p, %d)\n",
extensions->appleSpecBlob.data,
extensions->appleSpecBlob.length);
}
#if PKI_CHECK_KEY_IDS
else if (DEROidCompare(&oidSubjectKeyIdentifier, &extn.extnID)) {
require_noerr(extension_octet_string_value(&extn, false,
&extensions->subjectKeyID), out);
dprintf(DEBUG_SPEW, "found subject key id extension (%p, %d)\n",
extensions->subjectKeyID.data,
extensions->subjectKeyID.length);
}
else if (DEROidCompare(&oidAuthorityKeyIdentifier, &extn.extnID)) {
DERAuthorityKeyIdentifier authority_key_id_seq;
require_noerr(DERParseSequence(&extn.extnValue,
DERNumAuthorityKeyIdentifierItemSpecs,
DERAuthorityKeyIdentifierItemSpecs,
&authority_key_id_seq,
sizeof(authority_key_id_seq)), out);
if (authority_key_id_seq.keyIdentifier.length) {
extensions->authorityKeyID =
authority_key_id_seq.keyIdentifier;
dprintf(DEBUG_SPEW, "found auth key id extension (%p, %d)\n",
extensions->authorityKeyID.data,
extensions->authorityKeyID.length);
}
}
#endif
}
}
return 0;
out:
return -1;
}
static inline int dercmp(const DERItem a, const DERItem b)
{
if (a.length != b.length)
return -1;
if (memcmp(a.data, b.data, a.length))
return -1;
return 0;
}
/* Take a byte string and reverse it: giants layout on little endian */
static int rsa_set_giant(uint8_t *destination, size_t *dest_len,
uint8_t *source, size_t length, bool should_trim)
{
size_t len = length;
uint8_t *end = source;
uint8_t *dst = destination;
if(should_trim) {
/* ASN.1 integers may start with a zero to avoid sign interpretation */
if( len && !(*end) ) {
end++;
len--;
}
}
/* If it won't fit or zero we won't continue */
if (!len || len > *dest_len) {
*dest_len = 0;
return -1;
}
/* Reverse bytes: bignums start with lsb, word size doesn't matter for
little endian */
uint8_t *src = source+length-1;
while (src >= end)
*dst++ = *src--;
*dest_len = len;
return 0;
}
#if WITH_HW_PKE
/* Verify signed encoded digest info with rsa pubKey against signature */
static int verify_pkcs1_sig(const DERItem *pubKey /* PKCS1 format */,
const DERItem *digest_info, const DERItem *sig)
{
DERItem keyItem = {(DERByte *)pubKey->data, pubKey->length};
DERRSAPubKeyPKCS1 decodedKey;
struct {
uint8_t pmod[256];
uint8_t base[256];
uint8_t expn[256];
uint8_t mods[256];
size_t pmod_length;
size_t base_length;
size_t expn_length;
size_t mods_length;
size_t key_length;
} request;
require_noerr(DERParseSequence(&keyItem,
DERNumRSAPubKeyPKCS1ItemSpecs, DERRSAPubKeyPKCS1ItemSpecs,
&decodedKey, sizeof(decodedKey)), out);
bzero(&request, sizeof(request));
request.pmod_length = sizeof(request.pmod);
request.base_length = sizeof(request.base);
request.expn_length = sizeof(request.expn);
request.mods_length = sizeof(request.mods);
//Modulus and expn can have a leading zero padded to indicate a positive num.
//So trim those zeros out.
require_noerr(rsa_set_giant(request.mods, &request.mods_length,
decodedKey.modulus.data, decodedKey.modulus.length, true), out);
require_noerr(rsa_set_giant(request.expn, &request.expn_length,
decodedKey.pubExponent.data, decodedKey.pubExponent.length, true), out);
require_noerr(rsa_set_giant(request.base, &request.base_length,
sig->data, sig->length, false), out);
request.key_length = request.mods_length * 8;
require(pke_do_exp(request.pmod, &request.pmod_length,
request.key_length,
request.base, request.base_length,
request.expn, request.expn_length,
request.mods, request.mods_length), out);
/* verify padding: 0x00, 0x01, 0xff**0xff, 0x00, {algid, hash}: */
/* minimal pad length; digest_info->length although passed in is fixed. */
require(request.pmod_length >= digest_info->length + 11, out);
uint8_t *ptr = request.pmod + request.pmod_length - 1;
uint8_t *end = request.pmod;
uint8_t result = 0;
/* start with 0 */
result |= *ptr-- ^ 0;
require(ptr>end, out);
/* block type 1 */
result |= *ptr-- ^ 1;
require(ptr>end, out);
/* all 0xff */
while (*ptr == 0xff) {
require(ptr>end, out);
ptr--;
}
/* terminated by 0 */
result |= *ptr-- ^ 0;
require(ptr>end, out);
/* digest_info->length bytes left */
require(end + digest_info->length - 1 == ptr, out);
uint8_t *hash = digest_info->data;
/* match SHA-1 hash */
while (ptr>=end) {
result |= *ptr-- ^ *hash++;
}
require(result == 0, out);
return 0;
out:
return -1;
}
#else /* !WITH_HW_PKE */
/*
* Verify a PKCS1 signature with an RSA key. Caller is responsible for
* EncodedDigestInfo formatting.
*/
static int verify_pkcs1_sig(
const DERItem *pubKey, /* PKCS1 format */
const DERItem *toVerify,
const DERItem *sig)
{
RSAPubGiantKey rsaPubKey;
RSAStatus rrtn;
GI_CHECK_SP("verifyPkcs1Sig");
/*
* Convert PKCS1 format key to native libgRSA key.
* Ideally we'd like to have the key in Apple Custom form,
* with the reciprocal, obtainable from cert,
* Someday maybe.
*/
GI_LOG_SP("calling RSA_DecodePubKey");
rrtn = RSA_DecodePubKey(pubKey->data, pubKey->length, &rsaPubKey);
require_noerr(rrtn, out);
GI_LOG_SP("calling RSA_SigVerify");
rrtn = RSA_SigVerify(&rsaPubKey, RP_PKCS1,
(const gi_uint8 *)toVerify->data, (gi_uint16)toVerify->length,
(const gi_uint8 *)sig->data, (gi_uint16)sig->length);
require_noerr(rrtn, out);
return 0;
out:
return -1;
}
#endif
/*
* Given data to sign or verify, take the SHA1 digest of it and encode the result in
* an EncodedDigestInfo. The result is DER_SHA1_DIGEST_INFO_LEN bytes, allocated by the
* caller.
*/
static int sha1DigestInfo(const DERItem *ptext, unsigned char *digestInfo)
/* DER_SHA1_DIGEST_INFO_LEN bytes RETURNED */
{
DERByte digest[DER_SHA1_DIGEST_LEN];
DERReturn resultLen = DER_SHA1_DIGEST_INFO_LEN;
/* take the SHA1 digest */
sha1_calculate(ptext->data, ptext->length, digest);
/* now roll it into an EncodedDigestInfo */
return DEREncodeSHA1DigestInfo(digest, DER_SHA1_DIGEST_LEN,
digestInfo, &resultLen);
}
/* decode an algorithm ID */
static int decodeAlgId(const DERItem *encodedAlgId, DERAlgorithmId *decodedAlgId)
{
return DERParseSequenceContent(encodedAlgId,
DERNumAlgorithmIdItemSpecs, DERAlgorithmIdItemSpecs,
decodedAlgId, sizeof(*decodedAlgId));
}
/*
* Obtain a PKCS1-format public key from a SubjectPubKeyInfo (tbs.subjectPubKey).
*/
static int decodePubKey(DERItem *pubKeyInfoContent, DERItem *pubKeyPkcs1)
{
DERSubjPubKeyInfo pubKeyInfo;
DERByte numUnused;
DERAlgorithmId algId;
/* sequence we're given: encoded DERSubjPubKeyInfo */
require_noerr(DERParseSequenceContent(pubKeyInfoContent,
DERNumSubjPubKeyInfoItemSpecs, DERSubjPubKeyInfoItemSpecs,
&pubKeyInfo, sizeof(pubKeyInfo)), out);
/* verify that this is an RSA key by decoding the AlgId */
require_noerr(decodeAlgId(&pubKeyInfo.algId, &algId), out);
require(DEROidCompare(&algId.oid, &oidRsa), out);
/*
* The contents of pubKeyInfo.pubKey is a bit string whose contents
* are a PKCS1 format RSA key.
*/
require_noerr(DERParseBitString(&pubKeyInfo.pubKey, pubKeyPkcs1, &numUnused), out);
return 0;
out:
return -1;
}
static int crack_chain(DERItem *certblob, DERItem chain[], DERShort chain_len)
{
DERItem der_iter = *certblob;
DERShort num = 0;
DERSize used;
DERDecodedInfo topDecode;
dprintf(DEBUG_SPEW, "PKI: break certificate chain into certs\n");
do {
require_noerr(DERDecodeItem(&der_iter, &topDecode), out);
used = topDecode.content.data + topDecode.content.length - der_iter.data;
require(used < (128 * 1024), out); //no single cert larger than 128k
require(der_iter.length >= used, out);
require(num < chain_len, out);
chain[num].length = used;
chain[num].data = der_iter.data;
num++;
der_iter.length -= used;
der_iter.data += used;
} while (der_iter.length > 0);
#if PKI_CHECK_ANCHOR_BY_SHA1
/* require 3 element long chain */
require(num == chain_len, out);
/* check SHA-1 of (whole) root certificate (Apple root CA) */
dprintf(DEBUG_SPEW, "PKI: check SHA-1 of root\n");
unsigned char sha1[DER_SHA1_DIGEST_LEN];
sha1_calculate(chain[0].data, chain[0].length, sha1);
require_noerr(memcmp(ROOT_CA_SHA1_HASH, sha1, DER_SHA1_DIGEST_LEN), out);
#else
/* make room for root CA */
if (num == chain_len - 1) {
DERShort index;
for (index = chain_len - 1; index > 0; index--)
chain[index] = chain[index - 1];
}
else
require(num == chain_len, out);
/* use embedded root ca; override if one was passed in */
dprintf(DEBUG_SPEW, "PKI: anchor chain to %s CA\n",
PKI_APPLE_ROOT_CA ? "Apple" : "fake");
chain[0].data = (u_int8_t*)&ROOT_CA_CERTIFICATE;
chain[0].length = sizeof(ROOT_CA_CERTIFICATE);
#endif /* PKI_CHECK_ANCHOR_BY_SHA1 */
return 0;
out:
return -1;
}
static int parse_chain(DERItem chain[], DERShort chain_len,
DERSignedCertCrl chainElements[], DERTBSCert tbsCerts[],
DERItem derPubKey[], DERExtensions extensions[])
{
DERShort num = 0;
/* top level decode */
for (num = 0; num < chain_len; num++) {
dprintf(DEBUG_SPEW, "PKI: parse cert %d of %d\n", num + 1, chain_len);
require_noerr(DERParseSequence(&chain[num],
DERNumSignedCertCrlItemSpecs, DERSignedCertCrlItemSpecs,
&chainElements[num], sizeof(*chainElements)), out);
require_noerr(DERParseSequence(&chainElements[num].tbs,
DERNumTBSCertItemSpecs, DERTBSCertItemSpecs,
&tbsCerts[num], sizeof(*tbsCerts)), out);
require_noerr(decodePubKey(&tbsCerts[num].subjectPubKey, &derPubKey[num]), out);
require_noerr(parse_extensions(&tbsCerts[num], &extensions[num]), out);
}
return 0;
out:
return -1;
}
static int verify_chain_signatures(
DERItem *issuerPubKey,
DERSignedCertCrl *signedCert)
{
DERAlgorithmId algId;
unsigned char digestInfo[DER_SHA1_DIGEST_INFO_LEN];
DERByte numUnused;
DERItem toVerify = { digestInfo, DER_SHA1_DIGEST_INFO_LEN };
DERItem sigBytes;
/* figure out which digest to use from the sig algId */
require_noerr(decodeAlgId(&signedCert->sigAlg, &algId), out);
/* get the encodedDigestInfo from the digest of the subject's TBSCert */
require(DEROidCompare(&algId.oid, &oidSha1Rsa), out);
/* generate digest info from plaintext */
require_noerr(sha1DigestInfo(&signedCert->tbs, digestInfo), out);
/* get contents of sig, a bit string, as raw bytes */
require_noerr(DERParseBitString(&signedCert->sig, &sigBytes, &numUnused), out);
require_noerr(verify_pkcs1_sig(issuerPubKey, &toVerify, &sigBytes), out);
return 0;
out:
return -1;
}
/* find first value for oid */
static int find_content_by_oid(const DERItem *rdnSetContent,
const DERItem *oid, DERItem *content)
{
DERReturn drtn;
DERSequence rdn;
DERDecodedInfo atvContent;
DERAttributeTypeAndValue atv;
require_noerr(DERDecodeSeqContentInit(rdnSetContent, &rdn), out);
while ((drtn = DERDecodeSeqNext(&rdn, &atvContent)) == DR_Success) {
require(atvContent.tag == ASN1_CONSTR_SEQUENCE, out);
require_noerr(DERParseSequenceContent(&atvContent.content,
DERNumAttributeTypeAndValueItemSpecs,
DERAttributeTypeAndValueItemSpecs,
&atv, sizeof(atv)), out);
if (DEROidCompare(oid, &atv.type)) {
*content = atv.value;
return 0;
}
}
return drtn;
out:
return -1;
}
static int parse_common_name(const DERItem *subject, const DERItem *oid, DERItem *content)
{
DERSequence derSeq;
DERDecodedInfo currDecoded;
require_noerr(DERDecodeSeqContentInit(subject, &derSeq), out);
while (DERDecodeSeqNext(&derSeq, &currDecoded) == DR_Success) {
require(currDecoded.tag == ASN1_CONSTR_SET, out);
/* only if we reached the end of a sequence do we keep looking */
int status = find_content_by_oid(&currDecoded.content, oid, content);
if (status != DR_EndOfSequence)
return status;
}
out:
return -1;
}
static int verify_signature_with_hash(DERItem *public_key_pkcs1_rsa,
unsigned char *sig_blob, unsigned sig_blob_len,
unsigned char *hash_blob, unsigned hash_blob_len)
{
unsigned char digest_data[DER_SHA1_DIGEST_INFO_LEN];
DERItem signature = { sig_blob, sig_blob_len };
DERItem digest_info = { digest_data, sizeof(digest_data) };
/* generate digest info blob from hash */
require(hash_blob_len == DER_SHA1_DIGEST_LEN, out);
require_noerr(DEREncodeSHA1DigestInfo(hash_blob, hash_blob_len,
digest_info.data, &digest_info.length), out);
/* verify signature */
return verify_pkcs1_sig(public_key_pkcs1_rsa, &digest_info, &signature);
out:
return -1;
}
int verify_signature_with_chain(void *chain_blob, size_t chain_blob_length,
void *sig_blob, size_t sig_blob_len,
void *hash_blob, size_t hash_blob_len,
void **img3_spec_blob, size_t *img3_spec_blob_len,
void **ticket_spec_blob, size_t *ticket_spec_blob_len)
{
DERShort index;
const uint8_t chain_len = 3;
DERItem chain = { chain_blob, chain_blob_length };
DERItem certs[chain_len];
DERSignedCertCrl signedCert[chain_len];
DERTBSCert tbsCert[chain_len];
DERItem pubKeyPkcs1[chain_len];
DERExtensions extensions[chain_len];
require_noerr(crack_chain(&chain, certs, chain_len), out);
require_noerr(parse_chain(certs, chain_len, signedCert, tbsCert,
pubKeyPkcs1, extensions), out);
/* check linkage */
index = 1;
while (index < chain_len) {
dprintf(DEBUG_SPEW, "PKI: verify cert %d was issued by %d\n", index, index-1);
require_noerr(dercmp(tbsCert[index-1].subject,
tbsCert[index].issuer), out);
#if PKI_CHECK_KEY_IDS
require_noerr(dercmp(extensions[index-1].subjectKeyID,
extensions[index].authorityKeyID), out);
#endif
require_noerr(verify_chain_signatures(&pubKeyPkcs1[index-1], &signedCert[index]), out);
index++;
}
/* check common name intermediary cert to restrict to secure boot sub CA */
DERItem commonName = { NULL, 0 };
require_noerr(parse_common_name(&tbsCert[1].subject, &oidCommonName, &commonName), out);
// first character (0x13) - ASN1_PRINTABLE_STRING
// second character (0x29) - Length (copied over a cert)
static const DERByte sboot_common_name[] = "\x13\x29""Apple Secure Boot Certification Authority";
static const DERItem sboot_item = {
.data = (DERByte *)sboot_common_name,
.length = 0x2b
};
dprintf(DEBUG_SPEW, "PKI: check intermediate cert for common name '%s'\n", sboot_common_name);
require(DEROidCompare(&sboot_item, &commonName), out);
dprintf(DEBUG_SPEW, "PKI: check payload hash with signature\n");
require_noerr(verify_signature_with_hash(&pubKeyPkcs1[chain_len-1],
sig_blob, sig_blob_len, hash_blob, hash_blob_len), out);
/* return pointer to leaf blob in cert chain if it exists */
if (extensions[chain_len-1].appleSpecTicketBlob.data &&
extensions[chain_len-1].appleSpecTicketBlob.length) {
if (ticket_spec_blob != NULL && ticket_spec_blob_len != NULL) {
*ticket_spec_blob = extensions[chain_len-1].appleSpecTicketBlob.data;
*ticket_spec_blob_len = extensions[chain_len-1].appleSpecTicketBlob.length;
dprintf(DEBUG_SPEW, "PKI: parse apple spec id extension (ticket) in leaf: (%p, %zu)\n", *ticket_spec_blob, *ticket_spec_blob_len);
}
}
else if (extensions[chain_len-1].appleSpecBlob.data &&
extensions[chain_len-1].appleSpecBlob.length) {
if (img3_spec_blob != NULL && img3_spec_blob_len != NULL) {
*img3_spec_blob = extensions[chain_len-1].appleSpecBlob.data;
*img3_spec_blob_len = extensions[chain_len-1].appleSpecBlob.length;
dprintf(DEBUG_SPEW, "PKI: parse apple spec id extension (image3) in leaf: (%p, %zu)\n", *img3_spec_blob, *img3_spec_blob_len);
}
}
#if NO_DEFAULT_PLATFORM_PROVIDE_SPEC_BLOB
else /* ask the platform to provide a leaf blob */
{
DERTBSCert *leaf = &tbsCert[chain_len-1];
DERItem leafCommonName = { NULL, 0 };
require_noerr(parse_common_name(&leaf->subject, &oidCommonName, &leafCommonName), out);
require(platform_provide_spec_blob(leafCommonName.data, leafCommonName.length,
leaf->serialNum.data, leaf->serialNum.length,
img3_spec_blob, img3_spec_blob_len), out);
}
#endif // NO_DEFAULT_PLATFORM_PROVIDE_SPEC_BLOB
return 0;
out:
return -1;
}
+103
View File
@@ -0,0 +1,103 @@
/*
* Copyright (C) 2007-2010 Apple Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#include <debug.h>
#include <sys/menu.h>
#include <lib/pki.h>
#include <drivers/sha1.h>
#if defined(WITH_MENU) && WITH_MENU
int do_pki(int argc, struct cmd_arg *args)
{
int ret_val;
if (!security_allow_modes(kSecurityModeDebugCmd)) {
printf("Permission Denied\n");
return -1;
}
if (argc < 2) {
printf("not enough arguments.\n");
usage:
printf("%s verify <cert-chain-as-concatenated-der-blobs-data> <length> "
"<signature-blob-data> <length> <hash-blob-data> <length>\n", args[0].str);
printf("\tverify-image <8900-1.0-image-data> <length>\n");
return -1;
}
void *chain_data, *sig_blob, *hash_blob, *spec_blob;
size_t chain_len, sig_blob_len, hash_blob_len, spec_blob_len;
chain_data = sig_blob = hash_blob = spec_blob = NULL;
chain_len = sig_blob_len = hash_blob_len = spec_blob_len = 0;
if (!strcmp("verify", args[1].str)) {
if (argc < 8) {
printf("not enough arguments.\n");
goto usage;
}
chain_data = (void *)args[2].u;
chain_len = args[3].u;
sig_blob = (void *)args[4].u;
sig_blob_len = args[5].u;
hash_blob = (void *)args[6].u;
hash_blob_len = args[7].u;
} else if (!strcmp("verify-image", args[1].str)) {
if (argc < 4) {
printf ("not enough arguments.\n");
goto usage;
}
if (!strcmp("89001.0", (void*)args[2].u)) {
printf ("invalid image (only 8900 1.0 images)\n");
return -1;
}
uint8_t *payload = (uint8_t*)(args[2].u + 0x800);
uint8_t *signature = payload + *(uint32_t*)(args[2].u + 16);
uint8_t *chain = payload + *(uint32_t*)(args[2].u + 20);
chain_data = chain;
chain_len = args[2].u + args[3].u - (size_t)chain;
sig_blob = signature;
sig_blob_len = chain - signature;
/* abuse part of header as scratch */
uint8_t sha1_buf[20];
/* header + image are hashed for rsa verification */
sha1_calculate((uint8_t*)args[2].u, (size_t)signature - args[2].u, sha1_buf);
//sha1_calculate(payload, signature - payload, sha1_buf);
hash_blob = sha1_buf;
hash_blob_len = sizeof(sha1_buf);
} else
return -1;
ret_val = verify_signature_with_chain(chain_data, chain_len,
sig_blob, sig_blob_len, hash_blob, hash_blob_len,
&spec_blob, &spec_blob_len, NULL, NULL);
printf("signature verification returned: %d\n", ret_val);
return 0;
}
// Turned off to save space, enable as needed
// MENU_COMMAND_DEBUG(pki, do_pki, "PKI", NULL);
#endif
+372
View File
@@ -0,0 +1,372 @@
/*
* Copyright (C) 2007 Apple Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
/*
See docs/chain_validation.txt for instructions on using these.
Including this file instead of apple_ca.h will use this chain.
All keys and certs in pem format at the end of the file.
*/
#ifndef __FAKE_CA_H
#define __FAKE_CA_H
#if PKI_CHECK_ANCHOR_BY_SHA1
static const unsigned char ROOT_CA_SHA1_HASH[20] = {
0xeb, 0xb8, 0xaf, 0x3f, 0x77, 0xe4, 0x9d, 0xdc, 0x73, 0xa4,
0x54, 0x53, 0x8e, 0x40, 0xbb, 0x9c, 0xb1, 0x31, 0xe5, 0x7f
};
#else
static const unsigned char ROOT_CA_CERTIFICATE[931] = {
0x30,0x82,0x03,0x9F,0x30,0x82,0x02,0x87,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x00,
0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,
0x62,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,
0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,
0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,0x1D,0x41,0x70,
0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,
0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x16,0x30,0x14,0x06,
0x03,0x55,0x04,0x03,0x13,0x0D,0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,
0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x30,0x37,0x31,0x32,0x30,0x38,0x30,0x31,0x30,
0x38,0x31,0x37,0x5A,0x17,0x0D,0x30,0x38,0x30,0x31,0x30,0x37,0x30,0x31,0x30,0x38,
0x31,0x37,0x5A,0x30,0x62,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,
0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,
0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,
0x13,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,
0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,
0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x03,0x13,0x0D,0x41,0x70,0x70,0x6C,0x65,0x20,
0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,
0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,
0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xCD,0x91,0x86,0x6A,0x55,0x2D,0xE1,0xBA,
0x4F,0x04,0x38,0xD8,0x54,0x96,0xAC,0x7F,0x5C,0x02,0x24,0xC9,0x7C,0x15,0xA1,0x98,
0x08,0x8A,0x0D,0x72,0x00,0x92,0x4F,0x5A,0x86,0x31,0xA4,0x17,0x79,0x9F,0xAB,0x07,
0x11,0xA4,0x59,0x92,0x69,0x77,0x7A,0x7E,0xB3,0x95,0x2D,0x45,0x9B,0x67,0x02,0x15,
0x11,0x6A,0xD5,0xAF,0xC3,0x4E,0x97,0xD5,0xCC,0xE1,0x12,0x4B,0x80,0xE1,0x5E,0xBE,
0x5D,0x65,0x9C,0x5F,0x98,0x32,0xE1,0x31,0x5B,0x18,0xE5,0xBC,0xE0,0x27,0xE7,0xF0,
0xA9,0x1E,0xD7,0xBC,0xA5,0x09,0xC9,0xD5,0x79,0xFD,0x60,0x6A,0x33,0x69,0xFD,0x9C,
0xD2,0xEC,0x67,0x21,0xFB,0x74,0x87,0x99,0x4B,0x12,0xBA,0xCD,0xF9,0xE0,0xC0,0x37,
0x66,0x81,0x67,0x21,0xA6,0x78,0xA7,0x83,0x63,0x2C,0xE7,0xC7,0xCF,0x1C,0x09,0xE3,
0x23,0x29,0x7B,0x9F,0x4D,0x96,0xCC,0x21,0xC6,0x02,0x91,0xB0,0x4E,0xFD,0x6D,0x2F,
0x5B,0x03,0xE2,0xB9,0x35,0xE3,0x34,0xF1,0xCE,0x52,0xDF,0x79,0xE9,0x32,0x76,0x65,
0xE6,0x8B,0xEE,0xAB,0x4E,0x6A,0xBB,0x86,0xE4,0x4B,0x3E,0xB2,0xF7,0x5D,0x52,0x72,
0x11,0x1C,0x53,0x34,0xB6,0xF4,0x3B,0x4C,0x72,0x48,0xCC,0x53,0xD8,0xD8,0x13,0x5F,
0xFA,0x3C,0x35,0xC9,0x48,0x20,0x65,0xB3,0x19,0xEC,0x92,0xEC,0xA9,0xDE,0xF4,0xDB,
0x17,0x85,0xFE,0x16,0xBB,0x14,0x8E,0x85,0x6D,0x9D,0x94,0x5F,0x43,0x40,0x27,0xDE,
0x50,0x7B,0xC2,0x20,0x75,0x32,0x63,0xA9,0xEE,0x00,0x87,0xF3,0x72,0xAC,0x97,0x06,
0xB9,0xE5,0x3B,0x60,0x68,0xED,0x7D,0x3D,0x02,0x03,0x01,0x00,0x01,0xA3,0x60,0x30,
0x5E,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x4A,0x89,0x32,0x92,
0xFE,0x36,0x4C,0x31,0xA5,0x40,0x73,0x48,0xC9,0x2D,0x7F,0xCF,0xB5,0xBC,0x81,0xE1,
0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x4A,0x89,0x32,
0x92,0xFE,0x36,0x4C,0x31,0xA5,0x40,0x73,0x48,0xC9,0x2D,0x7F,0xCF,0xB5,0xBC,0x81,
0xE1,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,
0x01,0xFF,0x30,0x0B,0x06,0x03,0x55,0x1D,0x0F,0x04,0x04,0x03,0x02,0x07,0x80,0x30,
0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,
0x01,0x01,0x00,0xBC,0x57,0xEF,0x27,0x67,0xCA,0xE0,0xCF,0xA3,0xD3,0xFC,0xFC,0xCE,
0xCB,0xFC,0xD9,0x12,0x24,0x45,0x1B,0xA4,0x57,0xAA,0x87,0x4B,0x8C,0xE2,0xC8,0xF4,
0x50,0x61,0xC6,0xBC,0xDF,0x7B,0x89,0x32,0x87,0x81,0xF8,0xBD,0x4E,0xBE,0x4D,0x2F,
0xF1,0x8F,0xF2,0xAB,0x8B,0x21,0x33,0xF7,0x69,0xEE,0xF6,0xB4,0x51,0x09,0x29,0x59,
0x33,0x2F,0xF6,0x60,0xEE,0xBD,0x7A,0x1D,0x87,0xA5,0x42,0xBA,0x05,0x1E,0x83,0x44,
0x47,0x8D,0xD0,0x9E,0x4C,0x43,0x76,0x23,0xE5,0xE4,0xEF,0xC8,0x5C,0x3C,0x94,0x94,
0x43,0x92,0x38,0x30,0x79,0x8C,0xC2,0x68,0x73,0xB3,0x64,0xE4,0x2A,0xD8,0xBD,0x89,
0x6B,0x59,0xBC,0xA6,0x9A,0xF0,0xCB,0xBD,0x88,0x7C,0xD9,0xAB,0xB1,0x9E,0x11,0x55,
0xB2,0x4B,0x53,0xCF,0xA0,0x06,0xCD,0xED,0x3E,0x27,0xFA,0x48,0xDE,0xD8,0x14,0x29,
0x74,0x8E,0xDA,0xB5,0x61,0x26,0xEE,0xD5,0x61,0xC7,0xE6,0x80,0xFD,0x52,0xA0,0x63,
0xAB,0xDF,0x72,0x7B,0xCA,0xBE,0x3A,0x2D,0xB6,0x01,0x0A,0x75,0x98,0x12,0x33,0x15,
0xA9,0x71,0x66,0xCF,0x1C,0xFB,0x7D,0x15,0xA0,0x06,0xD2,0x4D,0xC8,0x33,0x3E,0xDD,
0x28,0xF9,0xFB,0x3A,0x55,0xCB,0xF0,0x38,0x30,0x72,0xBB,0xB3,0xB8,0xC8,0x1A,0xD8,
0xF8,0xBC,0x83,0xD5,0x34,0xBA,0x54,0xC4,0xB0,0x03,0x56,0xF8,0xEB,0xCC,0x1B,0x66,
0xFA,0xB7,0xB0,0x56,0x21,0x01,0xD6,0xF3,0x81,0xE9,0x45,0xAB,0x72,0x0F,0xC7,0x91,
0xE6,0x49,0x05,0x87,0x18,0x91,0x41,0xF2,0x05,0xC9,0x02,0xA0,0xB2,0xA3,0x05,0xC6,
0x01,0x55,0xC9,
};
#endif /* PKI_CHECK_ANCHOR_BY_SHA1 */
/*
CA-cert.pem
-----BEGIN CERTIFICATE-----
MIIDnzCCAoegAwIBAgIBADANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQGEwJVUzET
MBEGA1UEChMKQXBwbGUgSW5jLjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlv
biBBdXRob3JpdHkxFjAUBgNVBAMTDUFwcGxlIFJvb3QgQ0EwHhcNMDcxMjA4MDEw
ODE3WhcNMDgwMTA3MDEwODE3WjBiMQswCQYDVQQGEwJVUzETMBEGA1UEChMKQXBw
bGUgSW5jLjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx
FjAUBgNVBAMTDUFwcGxlIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
ggEKAoIBAQDNkYZqVS3huk8EONhUlqx/XAIkyXwVoZgIig1yAJJPWoYxpBd5n6sH
EaRZkml3en6zlS1Fm2cCFRFq1a/DTpfVzOESS4DhXr5dZZxfmDLhMVsY5bzgJ+fw
qR7XvKUJydV5/WBqM2n9nNLsZyH7dIeZSxK6zfngwDdmgWchpning2Ms58fPHAnj
Iyl7n02WzCHGApGwTv1tL1sD4rk14zTxzlLfeekydmXmi+6rTmq7huRLPrL3XVJy
ERxTNLb0O0xySMxT2NgTX/o8NclIIGWzGeyS7Kne9NsXhf4WuxSOhW2dlF9DQCfe
UHvCIHUyY6nuAIfzcqyXBrnlO2Bo7X09AgMBAAGjYDBeMB0GA1UdDgQWBBRKiTKS
/jZMMaVAc0jJLX/PtbyB4TAfBgNVHSMEGDAWgBRKiTKS/jZMMaVAc0jJLX/PtbyB
4TAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIHgDANBgkqhkiG9w0BAQUFAAOC
AQEAvFfvJ2fK4M+j0/z8zsv82RIkRRukV6qHS4ziyPRQYca833uJMoeB+L1Ovk0v
8Y/yq4shM/dp7va0UQkpWTMv9mDuvXodh6VCugUeg0RHjdCeTEN2I+Xk78hcPJSU
Q5I4MHmMwmhzs2TkKti9iWtZvKaa8Mu9iHzZq7GeEVWyS1PPoAbN7T4n+kje2BQp
dI7atWEm7tVhx+aA/VKgY6vfcnvKvjottgEKdZgSMxWpcWbPHPt9FaAG0k3IMz7d
KPn7OlXL8DgwcruzuMga2Pi8g9U0ulTEsANW+OvMG2b6t7BWIQHW84HpRatyD8eR
5kkFhxiRQfIFyQKgsqMFxgFVyQ==
-----END CERTIFICATE-----
CA-csr.pem
-----BEGIN CERTIFICATE REQUEST-----
MIICpzCCAY8CAQAwYjELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkFwcGxlIEluYy4x
JjAkBgNVBAsTHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRYwFAYDVQQD
Ew1BcHBsZSBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
zZGGalUt4bpPBDjYVJasf1wCJMl8FaGYCIoNcgCST1qGMaQXeZ+rBxGkWZJpd3p+
s5UtRZtnAhURatWvw06X1czhEkuA4V6+XWWcX5gy4TFbGOW84Cfn8Kke17ylCcnV
ef1gajNp/ZzS7Gch+3SHmUsSus354MA3ZoFnIaZ4p4NjLOfHzxwJ4yMpe59Nlswh
xgKRsE79bS9bA+K5NeM08c5S33npMnZl5ovuq05qu4bkSz6y911SchEcUzS29DtM
ckjMU9jYE1/6PDXJSCBlsxnskuyp3vTbF4X+FrsUjoVtnZRfQ0An3lB7wiB1MmOp
7gCH83Kslwa55TtgaO19PQIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAGBMBoLj
HWo543VlbNi8r/x9lBADfumd5g2fcqQnilZbouxVdFmVPRAAwPJXHavkttRytnUI
47+ouL1WJqeltWCviH0MmlzRkFlX76GiwIqgLK53vXMCy34o1RQrKsjdl3uxaYs6
89EZdF7PHZC2u8nWXBteIXm6BLFd1lJx7bbIoRFTks3FMun422K4BCl1jzsdkztf
94ofavRcNf6xot2zaDHSTEEV0hXxLJxXd8YhaFkM8wS9u17ACgddIjLv0uS3fofP
YR8r7DWJS2aGrGYn6IONbEFWucsyvMAPQ5rP0zC3MdvoNqJosOmVFH55YIO+tG4J
O082aNdGmyFsXF0=
-----END CERTIFICATE REQUEST-----
CA-key.pem
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAzZGGalUt4bpPBDjYVJasf1wCJMl8FaGYCIoNcgCST1qGMaQX
eZ+rBxGkWZJpd3p+s5UtRZtnAhURatWvw06X1czhEkuA4V6+XWWcX5gy4TFbGOW8
4Cfn8Kke17ylCcnVef1gajNp/ZzS7Gch+3SHmUsSus354MA3ZoFnIaZ4p4NjLOfH
zxwJ4yMpe59NlswhxgKRsE79bS9bA+K5NeM08c5S33npMnZl5ovuq05qu4bkSz6y
911SchEcUzS29DtMckjMU9jYE1/6PDXJSCBlsxnskuyp3vTbF4X+FrsUjoVtnZRf
Q0An3lB7wiB1MmOp7gCH83Kslwa55TtgaO19PQIDAQABAoIBAC5lBKgk90j1qnWy
eqiEpQPNeTJiQt4C7XQn7CbpmBvOu3CiryWk8o2S3rvUfncXr1bKeUA3dYUTyi2J
crSqnTwElFtzrO+wWVhs4WD10a3fXMb+uqUAfKllEe/wxHK0GbkBhWwSlH5HkZcH
I7VDtILVXbHJYPbnitlYpTUEBEERz2EoRkIEEKk4wZp2gLleyg5uwnmX+p6yvFN9
98/ArBQ4Med6heOw4gqUxP/zfBllmMQYoi8jUd+oZlLYJ35bErbeXSwsgCcDtdQw
s6acs9GDjF3+lhgVqUczBcd80jJRWqrJjNDbI0L/t6GxyS/b4qG80vApxgfCJBTY
cGK4cyECgYEA9L9S7gry9sCEQj+2/z2wt1oZh69bSev2QY1hqfYZ0ktAomk5R4h8
Ta4yJBOnftaTWkEYw6cBm/vMBFNxpYa4BnY6PWQwBh34Y+u9IUPo0zZ4L/j2Et6e
idN8CgC0ZCadbjawY3S6ogyKDJKXKjdn2Fx0gUCx56CjXXiuPScQoiUCgYEA1wUQ
xHj8qyCoX6h11DEQsd1HnFFkD1QPj23YWt8zXTNUn47ODB7lLJDrC75uM+550+os
eOpALQDveOa+cOf9jUs4s8IGPfwxEfr/AJwauty8W7Ps//HAPCuCLIkLJIWLhbDc
RW1bM/xV3uIcdp6cTjnbj6wuV4QRJtJqiQ8i5zkCgYBmZGyzfg0rwlsSxEkw+4Ql
ESLBK1HL2VYLErUbQASJgEYoLFF0ZdtrPEdp5Hccj3TSO426vPHlajBuVuKi13vB
6FBxQqr8xCkY1JUph5muU4lwuH1qY4x8KOgp3yWZCLawV1zwHvO9u/U9UU7AsLFX
SUbMlF5Zg1EVV9m9Z8yDqQKBgAyl2KGl+D7cserGjv/HTxMXUBIK25bnO+8U6AgY
Xv4Zed3U2Zvu6U4gzCKptfPKEFJ90NXf+ZxsFKoI8KTVkJ2SEijIvfNBdWV4XS2d
ARmCyHWgdM1tXABuEr8p5ITmchmQGLTgxN+e9TIiHMiBdfJIBvlBiIxPUW72K5wa
TtRJAoGBALrY77WmwIv5NBl4Bw+NdDXAp7Dnpw8jzfxr4slJzm0Y1iNp8ru5JDiW
TZ0GCK1fCaPpi1SWq/0HaFrLelB0oGjbAG4256MFT/BOkYHc84zlPaBUADeH/kTr
6Xv4rGXdZTE2hMklQABW9xe2S5YHjKhgp0Iqx9R+T85nU/wphiWs
-----END RSA PRIVATE KEY-----
intermediate-cert.pem
-----BEGIN CERTIFICATE-----
MIIDtTCCAp2gAwIBAgIBEDANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQGEwJVUzET
MBEGA1UEChMKQXBwbGUgSW5jLjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlv
biBBdXRob3JpdHkxFjAUBgNVBAMTDUFwcGxlIFJvb3QgQ0EwHhcNMDcxMjA4MDEw
ODMzWhcNMDgwMTA3MDEwODMzWjB+MQswCQYDVQQGEwJVUzETMBEGA1UEChMKQXBw
bGUgSW5jLjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx
MjAwBgNVBAMTKUFwcGxlIFNlY3VyZSBCb290IENlcnRpZmljYXRpb24gQXV0aG9y
aXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvcWxBbLPL3G9uKlf
zEGg9bBBTm9T2Wzl3/GlkcWZwbaZlutTIr9ywzm454FSBgZd+bhsktYm3JJrJe29
guj0FGN0x8AnBg0dzqBixGNNwA8YMPEnSxCvbtHxL90QAyv+bggx1MD4eXbuPMpq
n3hgHlLqbMVQsUj8RG95wkRjRfHbQutczqenlz69mxOUd1HY5LzLu+yu2Dm0FSPj
wzCadPTZ3gPos8lBvHt5B2Ty/+6tXHhBYHq4FofmJY0ADRoQrm4Ml8oHtu94Djh+
UCtXyC8G36to/j5C+FTYB6cPY33hTTlc+8OPBzijYp1h7lrcLvafpfWIZAXbTGg4
ldxvMwIDAQABo1owWDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAdBgNVHQ4EFgQU
xHwjblG8rtg2lGhCMHm3qSudO7wwHwYDVR0jBBgwFoAUSokykv42TDGlQHNIyS1/
z7W8geEwDQYJKoZIhvcNAQEFBQADggEBALgw2Fs2N9jZ/BzGMfY6IO7PSMih5kEE
dQB7LLd3a/uKZNqG1ti6hUB3AQyEextndDht+iqNxtdHUs4MCJEwCa+uEVs+KnpL
Hn6x6hSDn2y1br45/o9TVI6k0auq+kHchiU/U8ZNiRoZNU62OsntEyS7qIQJ0iJf
6JhHSm11J3gAg3FmRsWeznO6lnHb04o0XYlmZTguZkzKHOguZC8qlyCnzLgLYOxI
Rpb3kpNcveMHN+0RBXMRIusX5+0x1/qRq7NuDmvEFocDXhcAubO69/mqm1EKbUGP
L6HnZRpVQiGliBP6lCJHdzKYqruVKx0GsBnQIK/GDWgNokddGHO2iEs=
-----END CERTIFICATE-----
intermediate-csr.pem
-----BEGIN CERTIFICATE REQUEST-----
MIICwzCCAasCAQAwfjELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkFwcGxlIEluYy4x
JjAkBgNVBAsTHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MTIwMAYDVQQD
EylBcHBsZSBTZWN1cmUgQm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3FsQWyzy9xvbipX8xBoPWwQU5v
U9ls5d/xpZHFmcG2mZbrUyK/csM5uOeBUgYGXfm4bJLWJtySayXtvYLo9BRjdMfA
JwYNHc6gYsRjTcAPGDDxJ0sQr27R8S/dEAMr/m4IMdTA+Hl27jzKap94YB5S6mzF
ULFI/ERvecJEY0Xx20LrXM6np5c+vZsTlHdR2OS8y7vsrtg5tBUj48MwmnT02d4D
6LPJQbx7eQdk8v/urVx4QWB6uBaH5iWNAA0aEK5uDJfKB7bveA44flArV8gvBt+r
aP4+QvhU2AenD2N94U05XPvDjwc4o2KdYe5a3C72n6X1iGQF20xoOJXcbzMCAwEA
AaAAMA0GCSqGSIb3DQEBBQUAA4IBAQAHxnIfeyxIYubX5xR0fpJKS7qA8+g7M5Dh
U8sikodTly6UJCIc0wDNCuJfHbS0r+YB3J0lITqp1vK27bm9mF7R73kAKCv07cHP
s0z1ukBuEJmFmXbhDji4hnsuOTPYI3zX5NT4Tvwh+o5zLHmPolaPe7/oJaVKjySC
Y8hzSc1QWYFuuxeOHBLna6Bma3UPMvHx3Tobx5sw4eh+7K7DPHUFRR8oZBDwZ9st
86LgVnIqjJz5Gh4f+AiZuyVrY6yVYzMEug4oltGcGOPcxnTK+4cfnPM5oSpYbKPz
wsznyTw5sqgMxawUUubs70ObRg05ctsBrlP2wxfUoeZmyIO2cLvz
-----END CERTIFICATE REQUEST-----
intermediate-key.pem
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAvcWxBbLPL3G9uKlfzEGg9bBBTm9T2Wzl3/GlkcWZwbaZlutT
Ir9ywzm454FSBgZd+bhsktYm3JJrJe29guj0FGN0x8AnBg0dzqBixGNNwA8YMPEn
SxCvbtHxL90QAyv+bggx1MD4eXbuPMpqn3hgHlLqbMVQsUj8RG95wkRjRfHbQutc
zqenlz69mxOUd1HY5LzLu+yu2Dm0FSPjwzCadPTZ3gPos8lBvHt5B2Ty/+6tXHhB
YHq4FofmJY0ADRoQrm4Ml8oHtu94Djh+UCtXyC8G36to/j5C+FTYB6cPY33hTTlc
+8OPBzijYp1h7lrcLvafpfWIZAXbTGg4ldxvMwIDAQABAoIBAQCvUe5DN3iVel0u
NrwcNh2AHb+XuN4cJrEQfWzbCVUNU6b9eJarqXdayP78Ucr3afZz+F/GIDZy3IpE
1iiYwqKMG34N9IWY35FEDYRxrtRrtQZCYOhOPzH0DdzmvTJH2+MIwGVZCpYDkU5z
twVeIpWaLjwJFRmBT85PYzV3tjqIqFnIzQhU8CRb52MFsyvTSpsycPAaLbnZ2wr2
KT9gOtCv61SKuTqPm2NhrYL34lJCHORySBe4Ts5vmjX75pBd00eDFTz6Fzwo9ePk
65nV3Vf7CKfqXLyV8ZHLU5xoMaPYvEY/mb1W1J+IsZ77juPAnQQ/aYqdUTDkjsq4
F5nJ3PlBAoGBAO5Z44eGsKclr1sVNo+QAchZqYSyyFKojKfnZHWztIfXdR9xZksg
zXSPQ0EbGdVK+ETDNZ4FWMCbllx69lLcnig8CN/6XKsKvjkw2mu0aS0I34RmozHo
mk2UV7KN3BLN8n7LSl1nucnI0mLFjZYpBQB/fnCS8F03TSDU97WEoupDAoGBAMvS
9LvcgfOUzIVD/MIJeYYxRJnroUcSijqs3Pp9ReWzRie9W7FOzM4gsSIs/wZh4dce
XIgS8mEobGTQH8dX5GostiKqJQq/E0Oa9i7QDmKOzVYqXjq+RuWu7GDmSb9kZ2g9
03GItxlwODNIAgpVT3p4FMDvTR+DsDdDF9jrMXBRAoGAFAOKPnQJ208nxU8nsLBX
5fnZaSIV/hLXFLYyUkvPqeRmmkhMXZyYg+QPsqTS630LEcMOeoFabXnjC0rr6hNK
WHiKCjyckWQqiuTWQlr4xeZL1nND2sn8Qu1k28Jbq1yNsyXgza0LBa2ONOr/s48o
M12BQXSlKD6fhFU9o4lKoL8CgYEAoH3XnyUeXkJIWJcUK2VyfyvELL7RGzmKBnGe
/s4tf5UOJLSBwredpKExWQu9M7VXMyABFFR27fH6h9cpbrnSbZgPQnRe/ns+G/mk
52+EJC71mGd8Ex1IjgqSriom38GbewVTvQ49vpYSaq7EjIZoMrLjBJhpTetPkfQO
jwuCvkECgYAqKEjuLbX+nhzQkd6pvz/69fTL1VyHZlvzS/ZDnSuJWQ1EgJDv39Q8
HLdFqzouNmfPU/dZiTPpOQTy2DYcRnFgwIhxKjrlSI8N3NtAjb5F78GixwfvsxVw
+jh3GPYgL9xXKDDgnaLdkhGNuHR2aEiAWpXlz5PURgSVMqR8tgKZnw==
-----END RSA PRIVATE KEY-----
leaf-dev-cert.pem
-----BEGIN CERTIFICATE-----
MIIDfjCCAmagAwIBAgIBAjANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJVUzET
MBEGA1UEChMKQXBwbGUgSW5jLjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlv
biBBdXRob3JpdHkxMjAwBgNVBAMTKUFwcGxlIFNlY3VyZSBCb290IENlcnRpZmlj
YXRpb24gQXV0aG9yaXR5MB4XDTA3MTIwODAxMDg0N1oXDTA4MDEwNzAxMDg0N1ow
dDELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkFwcGxlIEluYy4xMjAwBgNVBAsTKUFw
cGxlIFNlY3VyZSBCb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRwwGgYDVQQD
ExNTNUw4OTAwIFNlY3VyZSBCb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
gQDNOqtQo1chTGmwchCu3hh0FcibQJWXGV5aULDbfYZloDLJIXi2B1E7XaGr8NpF
cXYyoZxA1dy9Dl0A1wiiDXa8sw5bhv9LE4FZI4u6+vRmlsebFzjOrsTvDyaAVqF+
d3MLvEsZKNLYns9OePDchvUzAvA1F2ll8L8EWHb3cHPt8QIDAQABo4GUMIGRMAkG
A1UdEwQCMAAwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBSCGlh9KFcEUknDmU4ajg7N
fDvgjzAfBgNVHSMEGDAWgBTEfCNuUbyu2DaUaEIwebepK507vDA3BgoqhkiG92Nk
BgEBAQH/BCYEJDNnbUkkAAAAHAAAAAAAAAAqKioqRE9SUBAAAAAEAAAAAAAAADAN
BgkqhkiG9w0BAQUFAAOCAQEAbDrnROb31daOREElTOgBA6ExiRIz+3KSz/oIyZA3
7Qz28zwGFjqWQ3u4PIAxypVJn2vxYHDerR1uEkgQBXD+F2pR1rFDSwCKtBZoFpVb
F1cr9t99JaYKwX1BsYnsGWAfRiscDh/QrVEbUOujVkH71KI3qn1N3L0mEftmWSK0
mZXFvu4l7O/GdCWkPYrfvrImpHhfy/OiyhZq3iddmV4kjyBLiR87Z/hP0g81Ootg
I4LVeeps7Sq4MY2Q7uadq4EmK626DQknGGaiM+571pIqA26waBpHrPLAdMEn6F3G
YOsG5Q2eRj/tEUKr1S9a8UYMDA5uLRMaER92JZhCrfyM9Q==
-----END CERTIFICATE-----
leaf-dev-csr.pem
-----BEGIN CERTIFICATE REQUEST-----
MIIBtDCCAR0CAQAwdDELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkFwcGxlIEluYy4x
MjAwBgNVBAsTKUFwcGxlIFNlY3VyZSBCb290IENlcnRpZmljYXRpb24gQXV0aG9y
aXR5MRwwGgYDVQQDExNTNUw4OTAwIFNlY3VyZSBCb290MIGfMA0GCSqGSIb3DQEB
AQUAA4GNADCBiQKBgQDNOqtQo1chTGmwchCu3hh0FcibQJWXGV5aULDbfYZloDLJ
IXi2B1E7XaGr8NpFcXYyoZxA1dy9Dl0A1wiiDXa8sw5bhv9LE4FZI4u6+vRmlseb
FzjOrsTvDyaAVqF+d3MLvEsZKNLYns9OePDchvUzAvA1F2ll8L8EWHb3cHPt8QID
AQABoAAwDQYJKoZIhvcNAQEFBQADgYEAGaJSzXCAcED9t+FTz3rLo+MQieQ0r3TI
JC0OStaw/ixYJyp4/BAga7WAPsa35yJFJE+Rh/MeiG2skt4r3kH1w3/yAlfYGCET
XVyFypjE80cPTf6iveGdiBS7+Qx69y5uDnNMFX6XwvOxwjfkMXs0qyIEaSLCcjMW
ipMrF/xrqM4=
-----END CERTIFICATE REQUEST-----
leaf-dev-key.pem
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDNOqtQo1chTGmwchCu3hh0FcibQJWXGV5aULDbfYZloDLJIXi2
B1E7XaGr8NpFcXYyoZxA1dy9Dl0A1wiiDXa8sw5bhv9LE4FZI4u6+vRmlsebFzjO
rsTvDyaAVqF+d3MLvEsZKNLYns9OePDchvUzAvA1F2ll8L8EWHb3cHPt8QIDAQAB
AoGABR+Fz0mEj0w9By6RxAu/SIaSr215ToBPnqmNAK2tgTPykJrJTKH6ISVBN+2X
RUyDytfF8shj7kRBhhfYG1OCtz+9/jIvhzmq11AtNPK3Pm1i3L2kcD/lMIkqvn6H
Ck7Qif4TqU+CMDBgbsYw9wR5+rXdxUiX3Z2kT6ukcmutk8ECQQDsbgzFfk2MzdVi
ttA8VwwhUtYBY2dKI83zz53x6UDWd8vdlBKuPbzRp5H0ZGK5DzNFBBmy50ZgrGlr
uCR3U4ItAkEA3jd56oto/y4KeqXMFjaGLKXibKbKPFh0nGQU5MrjNODVrkKzXJ3r
NFWPqsU+vhgzF1pmwjdLJB0KWGJ91DKpVQJBANPkIUASXRA3HOm2a9PYM7/dzHw8
CUMR6a97v9MhuAE+JhB0d3V/US0YoB9GpI+0Rr+w2BNVYOadPnHS+6ORzRUCQHOm
c7D5tT95esKyHzFAVzxNaTYa6A3YC3iJLcaVQQJ4MT1sQWTmW071aLv7w9ezSIPS
7MAPfu/gnU26lLonU7ECQQDUpwN5dnJWRaKyvQbVZ5Zfs9R3+N5rB+dbhaqDCJu5
rtRR/C4jvPMebqsJqVIedgbED+Ci5IkobXQxsXf9k5SI
-----END RSA PRIVATE KEY-----
leaf-prod-cert.pem
-----BEGIN CERTIFICATE-----
MIIDfjCCAmagAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJVUzET
MBEGA1UEChMKQXBwbGUgSW5jLjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlv
biBBdXRob3JpdHkxMjAwBgNVBAMTKUFwcGxlIFNlY3VyZSBCb290IENlcnRpZmlj
YXRpb24gQXV0aG9yaXR5MB4XDTA3MTIwODAxMDg0MVoXDTA4MDEwNzAxMDg0MVow
dDELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkFwcGxlIEluYy4xMjAwBgNVBAsTKUFw
cGxlIFNlY3VyZSBCb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRwwGgYDVQQD
ExNTNUw4OTAwIFNlY3VyZSBCb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
gQDPaf0eFpjLc2XOvMNipZd5soFkn8bcu7zUkULxkPKT5ykO8fmfzzJPQIdHNFt3
6hnJ0y+WCAlWebfVcMXhUOcN2DLbhHKog4+WN/A84dyW3U4JPkJbnAdnxvsNOtmY
6CJMsrX0tYFjMc1/b9KVLve1tEmPQdxq8iAQA9P1oS2AyQIDAQABo4GUMIGRMAkG
A1UdEwQCMAAwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTxKP1pOKrSvJj+7r3Lzbki
VNRpFTAfBgNVHSMEGDAWgBTEfCNuUbyu2DaUaEIwebepK507vDA3BgoqhkiG92Nk
BgEBAQH/BCYEJDNnbUkkAAAAHAAAAAAAAAAqKioqRE9SUBAAAAAEAAAAAQAAADAN
BgkqhkiG9w0BAQUFAAOCAQEAZcm1Ea/tIy3vvZsR1ysPukLsXc4/jgE4Yavion53
LzwGq2cotdrInvnwiILl6QOv1q+ND+h+kOpiNOagX8KPgnjvw3PWeo+EDfqjgBVS
1T+e3c7Bh5bjfxJUdP29X/Np652mTQcgxd1YI/ie1hYzjG5+pjHpDpT79gRnk4MV
/bdzqIXMVPgo5D3vIe4mnrY/TmTj4m13aLzF0FNlidyX5kSPrGfPTnGxnXXrjr/3
oF28d1PLHVcnkjppxGrKxUqTPJK5NKIVApV0X7VuBeG3hGN4+RDHDYL9brwj1Ub+
OTQbe1nfsaPh8JDSpXQh4GeRYwi2OOCYM+ooFv46Cx4Pvg==
-----END CERTIFICATE-----
leaf-prod-csr.pem
-----BEGIN CERTIFICATE REQUEST-----
MIIBtDCCAR0CAQAwdDELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkFwcGxlIEluYy4x
MjAwBgNVBAsTKUFwcGxlIFNlY3VyZSBCb290IENlcnRpZmljYXRpb24gQXV0aG9y
aXR5MRwwGgYDVQQDExNTNUw4OTAwIFNlY3VyZSBCb290MIGfMA0GCSqGSIb3DQEB
AQUAA4GNADCBiQKBgQDPaf0eFpjLc2XOvMNipZd5soFkn8bcu7zUkULxkPKT5ykO
8fmfzzJPQIdHNFt36hnJ0y+WCAlWebfVcMXhUOcN2DLbhHKog4+WN/A84dyW3U4J
PkJbnAdnxvsNOtmY6CJMsrX0tYFjMc1/b9KVLve1tEmPQdxq8iAQA9P1oS2AyQID
AQABoAAwDQYJKoZIhvcNAQEFBQADgYEAgFpUWqgUUGi1jBzRvVQt/jyjA4C7T07y
mpgk3i/tNU8+r/3qT3FsXKPHkdLWat3lJiAKSU87KRDxg4ZLmyKa2qWjr6J5Dz15
3dtfaGJpH3tkEl39aXNm5NzkVWZ1hunU2MJp1zE6rgdrufOCLr5dehpXlzl4xBjy
8nMROVgE2Ig=
-----END CERTIFICATE REQUEST-----
leaf-prod-key.pem
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDPaf0eFpjLc2XOvMNipZd5soFkn8bcu7zUkULxkPKT5ykO8fmf
zzJPQIdHNFt36hnJ0y+WCAlWebfVcMXhUOcN2DLbhHKog4+WN/A84dyW3U4JPkJb
nAdnxvsNOtmY6CJMsrX0tYFjMc1/b9KVLve1tEmPQdxq8iAQA9P1oS2AyQIDAQAB
AoGALbdRyAj5Apbb0LaAZkTTX0p+BJzG6y4iD8Q4uh/Vp83imd2xxIyZrSgu6P3c
T1D1ACwhJ/N7g2juoQfrRZ9cXaXBrNHkttOPcdo3Ra4pbanGQu1JMpUlIHY5mEMU
zusVJg/RsjfIqOk4NvsbUava8fVTFw0SCdvgT5IE7t391TUCQQD+GwPKxAC8Tn+O
LbToIKyiyO4w0/EpVhdD5RdhBW+zfpLQO3mUs1YGmk487tI9QCNNy8DfV2LK/bDN
F6SrT6EzAkEA0PXbzyJ1XviLH3zQJrGfEHdOIu0mp15l/EC3Qtm1RISDsK7L/KdD
NNtABtgfL6nku9v+ewc0P2kzT0Elyj1OEwJBAIT6rERbyKrDRdupLchg+ReDoatp
7wYb6Lb+V/rNNoSv07MnvNvF8looPJOEw/+L5i3bWIdJGwlyNClQmzuPw6MCQAYf
LdFjsQyXO3wwq+h2S7KvzBo52GgO2+4H91Z+ClF3kGQcut0sCUwDIF0S99bto0Xd
rBbunxk8e8RWpETIhwECQQC62cv5HiWimw6X+qpS3Z/sEgRXbnlqTmtPPIsi3vGW
K7Q0pCXXvTyNSFE81Ds9Pgwn5j5FD1bL4txLBZZZS58r
-----END RSA PRIVATE KEY-----
*/
#endif /* __FAKE_CA_H */
+319
View File
@@ -0,0 +1,319 @@
/* Copyright (c) 2005-2009 Apple Inc. All Rights Reserved. */
/*
* DER_Cert.c - support for decoding X509 certificates
*
* Created Nov. 4 2005 by Doug Mitchell.
*/
#include <libDER/DER_Decode.h>
#include <libDER/DER_CertCrl.h>
#include <libDER/asn1Types.h>
/*
* DERItemSpecs for X509 certificates.
*/
/* top level cert with three components */
const DERItemSpec DERSignedCertCrlItemSpecs[] =
{
{ DER_OFFSET(DERSignedCertCrl, tbs),
ASN1_CONSTR_SEQUENCE,
DER_DEC_NO_OPTS | DER_DEC_SAVE_DER},
{ DER_OFFSET(DERSignedCertCrl, sigAlg),
ASN1_CONSTR_SEQUENCE,
DER_DEC_NO_OPTS },
{ DER_OFFSET(DERSignedCertCrl, sig),
ASN1_BIT_STRING,
DER_DEC_NO_OPTS }
};
const DERSize DERNumSignedCertCrlItemSpecs =
sizeof(DERSignedCertCrlItemSpecs) / sizeof(DERItemSpec);
/* TBS cert */
const DERItemSpec DERTBSCertItemSpecs[] =
{
{ DER_OFFSET(DERTBSCert, version),
ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC | 0,
DER_DEC_OPTIONAL }, /* version - EXPLICIT */
{ DER_OFFSET(DERTBSCert, serialNum),
ASN1_INTEGER,
DER_DEC_NO_OPTS },
{ DER_OFFSET(DERTBSCert, tbsSigAlg),
ASN1_CONSTR_SEQUENCE,
DER_DEC_NO_OPTS },
{ DER_OFFSET(DERTBSCert, issuer),
ASN1_CONSTR_SEQUENCE,
DER_DEC_NO_OPTS },
{ DER_OFFSET(DERTBSCert, validity),
ASN1_CONSTR_SEQUENCE,
DER_DEC_NO_OPTS },
{ DER_OFFSET(DERTBSCert, subject),
ASN1_CONSTR_SEQUENCE,
DER_DEC_NO_OPTS },
{ DER_OFFSET(DERTBSCert, subjectPubKey),
ASN1_CONSTR_SEQUENCE,
DER_DEC_NO_OPTS },
/* libsecurity_asn1 has these two as CONSTRUCTED, but the ASN.1 spec
* doesn't look that way to me. I don't have any certs that have these
* fields.... */
{ DER_OFFSET(DERTBSCert, issuerID),
ASN1_CONTEXT_SPECIFIC | 1,
DER_DEC_OPTIONAL },
{ DER_OFFSET(DERTBSCert, subjectID),
ASN1_CONTEXT_SPECIFIC | 2,
DER_DEC_OPTIONAL },
{ DER_OFFSET(DERTBSCert, extensions),
ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC | 3,
DER_DEC_OPTIONAL }
};
const DERSize DERNumTBSCertItemSpecs = sizeof(DERTBSCertItemSpecs) / sizeof(DERItemSpec);
/* DERValidity */
const DERItemSpec DERValidityItemSpecs[] =
{
{ DER_OFFSET(DERValidity, notBefore),
0, /* no tag - ANY */
DER_DEC_ASN_ANY | DER_DEC_SAVE_DER },
{ DER_OFFSET(DERValidity, notAfter),
0, /* no tag - ANY */
DER_DEC_ASN_ANY | DER_DEC_SAVE_DER }
};
const DERSize DERNumValidityItemSpecs =
sizeof(DERValidityItemSpecs) / sizeof(DERItemSpec);
/* DERAttributeTypeAndValue */
const DERItemSpec DERAttributeTypeAndValueItemSpecs[] = {
{ DER_OFFSET(DERAttributeTypeAndValue, type),
ASN1_OBJECT_ID,
DER_DEC_NO_OPTS },
{ DER_OFFSET(DERAttributeTypeAndValue, value),
0, /* no tag - ANY */
DER_DEC_ASN_ANY | DER_DEC_SAVE_DER }
};
const DERSize DERNumAttributeTypeAndValueItemSpecs =
sizeof(DERAttributeTypeAndValueItemSpecs) / sizeof(DERItemSpec);
/* DERExtension */
const DERItemSpec DERExtensionItemSpecs[] =
{
{ DER_OFFSET(DERExtension, extnID),
ASN1_OBJECT_ID,
DER_DEC_NO_OPTS },
{ DER_OFFSET(DERExtension, critical),
ASN1_BOOLEAN,
DER_DEC_OPTIONAL },
{ DER_OFFSET(DERExtension, extnValue),
ASN1_OCTET_STRING,
DER_DEC_NO_OPTS }
};
const DERSize DERNumExtensionItemSpecs =
sizeof(DERExtensionItemSpecs) / sizeof(DERItemSpec);
/* DERBasicConstraints */
const DERItemSpec DERBasicConstraintsItemSpecs[] =
{
{ DER_OFFSET(DERBasicConstraints, cA),
ASN1_BOOLEAN,
DER_DEC_OPTIONAL },
{ DER_OFFSET(DERBasicConstraints, pathLenConstraint),
ASN1_INTEGER,
DER_DEC_OPTIONAL }
};
const DERSize DERNumBasicConstraintsItemSpecs =
sizeof(DERBasicConstraintsItemSpecs) / sizeof(DERItemSpec);
/* DERPrivateKeyUsagePeriod. */
const DERItemSpec DERPrivateKeyUsagePeriodItemSpecs[] =
{
{ DER_OFFSET(DERPrivateKeyUsagePeriod, notBefore),
ASN1_CONTEXT_SPECIFIC | 0,
DER_DEC_OPTIONAL },
{ DER_OFFSET(DERPrivateKeyUsagePeriod, notAfter),
ASN1_CONTEXT_SPECIFIC | 1,
DER_DEC_OPTIONAL }
};
const DERSize DERNumPrivateKeyUsagePeriodItemSpecs =
sizeof(DERPrivateKeyUsagePeriodItemSpecs) / sizeof(DERItemSpec);
/* DERDistributionPoint. */
const DERItemSpec DERDistributionPointItemSpecs[] =
{
{ DER_OFFSET(DERDistributionPoint, distributionPoint),
ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0,
DER_DEC_OPTIONAL },
{ DER_OFFSET(DERDistributionPoint, reasons),
ASN1_CONTEXT_SPECIFIC | 1,
DER_DEC_OPTIONAL },
{ DER_OFFSET(DERDistributionPoint, cRLIssuer),
ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 2,
DER_DEC_OPTIONAL }
};
const DERSize DERNumDistributionPointItemSpecs =
sizeof(DERDistributionPointItemSpecs) / sizeof(DERItemSpec);
/* DERPolicyInformation. */
const DERItemSpec DERPolicyInformationItemSpecs[] =
{
{ DER_OFFSET(DERPolicyInformation, policyIdentifier),
ASN1_OBJECT_ID,
DER_DEC_NO_OPTS },
{ DER_OFFSET(DERPolicyInformation, policyQualifiers),
ASN1_CONSTR_SEQUENCE,
DER_DEC_OPTIONAL }
};
const DERSize DERNumPolicyInformationItemSpecs =
sizeof(DERPolicyInformationItemSpecs) / sizeof(DERItemSpec);
/* DERPolicyQualifierInfo. */
const DERItemSpec DERPolicyQualifierInfoItemSpecs[] =
{
{ DER_OFFSET(DERPolicyQualifierInfo, policyQualifierID),
ASN1_OBJECT_ID,
DER_DEC_NO_OPTS },
{ DER_OFFSET(DERPolicyQualifierInfo, qualifier),
0, /* no tag - ANY */
DER_DEC_ASN_ANY | DER_DEC_SAVE_DER }
};
const DERSize DERNumPolicyQualifierInfoItemSpecs =
sizeof(DERPolicyQualifierInfoItemSpecs) / sizeof(DERItemSpec);
/* DERUserNotice. */
const DERItemSpec DERUserNoticeItemSpecs[] =
{
{ DER_OFFSET(DERUserNotice, noticeRef),
ASN1_CONSTR_SEQUENCE,
DER_DEC_OPTIONAL },
{ DER_OFFSET(DERUserNotice, explicitText),
0, /* no tag - ANY */
DER_DEC_ASN_ANY | DER_DEC_OPTIONAL | DER_DEC_SAVE_DER }
};
const DERSize DERNumUserNoticeItemSpecs =
sizeof(DERUserNoticeItemSpecs) / sizeof(DERItemSpec);
/* DERNoticeReference. */
const DERItemSpec DERNoticeReferenceItemSpecs[] =
{
{ DER_OFFSET(DERNoticeReference, organization),
0, /* no tag - ANY */
DER_DEC_ASN_ANY | DER_DEC_SAVE_DER },
{ DER_OFFSET(DERNoticeReference, noticeNumbers),
ASN1_CONSTR_SEQUENCE,
DER_DEC_NO_OPTS }
};
const DERSize DERNumNoticeReferenceItemSpecs =
sizeof(DERNoticeReferenceItemSpecs) / sizeof(DERItemSpec);
/* DERPolicyMapping. */
const DERItemSpec DERPolicyMappingItemSpecs[] =
{
{ DER_OFFSET(DERPolicyMapping, issuerDomainPolicy),
ASN1_OBJECT_ID,
DER_DEC_NO_OPTS },
{ DER_OFFSET(DERPolicyMapping, subjectDomainPolicy),
ASN1_OBJECT_ID,
DER_DEC_NO_OPTS }
};
const DERSize DERNumPolicyMappingItemSpecs =
sizeof(DERPolicyMappingItemSpecs) / sizeof(DERItemSpec);
/* DERAccessDescription. */
const DERItemSpec DERAccessDescriptionItemSpecs[] =
{
{ DER_OFFSET(DERAccessDescription, accessMethod),
ASN1_OBJECT_ID,
DER_DEC_NO_OPTS },
{ DER_OFFSET(DERAccessDescription, accessLocation),
0, /* no tag - ANY */
DER_DEC_ASN_ANY | DER_DEC_SAVE_DER }
};
const DERSize DERNumAccessDescriptionItemSpecs =
sizeof(DERAccessDescriptionItemSpecs) / sizeof(DERItemSpec);
/* DERAuthorityKeyIdentifier. */
const DERItemSpec DERAuthorityKeyIdentifierItemSpecs[] =
{
{ DER_OFFSET(DERAuthorityKeyIdentifier, keyIdentifier),
ASN1_CONTEXT_SPECIFIC | 0,
DER_DEC_OPTIONAL },
{ DER_OFFSET(DERAuthorityKeyIdentifier, authorityCertIssuer),
ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1,
DER_DEC_OPTIONAL },
{ DER_OFFSET(DERAuthorityKeyIdentifier, authorityCertSerialNumber),
ASN1_CONTEXT_SPECIFIC | 2,
DER_DEC_OPTIONAL }
};
const DERSize DERNumAuthorityKeyIdentifierItemSpecs =
sizeof(DERAuthorityKeyIdentifierItemSpecs) / sizeof(DERItemSpec);
/* DEROtherName. */
const DERItemSpec DEROtherNameItemSpecs[] =
{
{ DER_OFFSET(DEROtherName, typeIdentifier),
ASN1_OBJECT_ID,
DER_DEC_NO_OPTS },
{ DER_OFFSET(DEROtherName, value),
ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0,
DER_DEC_NO_OPTS },
};
const DERSize DERNumOtherNameItemSpecs =
sizeof(DEROtherNameItemSpecs) / sizeof(DERItemSpec);
/* DERPolicyConstraints. */
const DERItemSpec DERPolicyConstraintsItemSpecs[] =
{
{ DER_OFFSET(DERPolicyConstraints, requireExplicitPolicy),
ASN1_CONTEXT_SPECIFIC | 0,
DER_DEC_OPTIONAL },
{ DER_OFFSET(DERPolicyConstraints, inhibitPolicyMapping),
ASN1_CONTEXT_SPECIFIC | 1,
DER_DEC_OPTIONAL }
};
const DERSize DERNumPolicyConstraintsItemSpecs =
sizeof(DERPolicyConstraintsItemSpecs) / sizeof(DERItemSpec);
/* DERTBSCrl */
const DERItemSpec DERTBSCrlItemSpecs[] =
{
{ DER_OFFSET(DERTBSCrl, version),
ASN1_INTEGER,
DER_DEC_OPTIONAL },
{ DER_OFFSET(DERTBSCrl, tbsSigAlg),
ASN1_CONSTR_SEQUENCE,
DER_DEC_NO_OPTS },
{ DER_OFFSET(DERTBSCrl, issuer),
ASN1_CONSTR_SEQUENCE,
DER_DEC_NO_OPTS },
{ DER_OFFSET(DERTBSCrl, thisUpdate),
0, /* no tag - ANY */
DER_DEC_ASN_ANY | DER_DEC_SAVE_DER },
{ DER_OFFSET(DERTBSCrl, nextUpdate),
0, /* no tag - ANY */
DER_DEC_ASN_ANY | DER_DEC_SAVE_DER },
{ DER_OFFSET(DERTBSCrl, revokedCerts),
ASN1_CONSTR_SEQUENCE,
DER_DEC_OPTIONAL },
{ DER_OFFSET(DERTBSCrl, extensions),
ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC | 0,
DER_DEC_OPTIONAL }
};
const DERSize DERNumTBSCrlItemSpecs = sizeof(DERTBSCrlItemSpecs) / sizeof(DERItemSpec);
/* DERRevokedCert */
const DERItemSpec DERRevokedCertItemSpecs[] =
{
{ DER_OFFSET(DERRevokedCert, serialNum),
ASN1_INTEGER,
DER_DEC_NO_OPTS },
{ DER_OFFSET(DERRevokedCert, revocationDate),
0, /* no tag - ANY */
DER_DEC_ASN_ANY | DER_DEC_SAVE_DER },
{ DER_OFFSET(DERRevokedCert, extensions),
ASN1_CONSTR_SEQUENCE,
DER_DEC_OPTIONAL }
};
const DERSize DERNumRevokedCertItemSpecs =
sizeof(DERRevokedCertItemSpecs) / sizeof(DERItemSpec);
+233
View File
@@ -0,0 +1,233 @@
/* Copyright (c) 2005-2009 Apple Inc. All Rights Reserved. */
/*
* DER_CertCrl.h - support for decoding X509 certificates and CRLs
*
* Created Nov. 4 2005 by dmitch
*/
#ifndef _DER_CERT_CRL_H_
#define _DER_CERT_CRL_H_
#include <libDER/libDER.h>
#include <libDER/DER_Decode.h>
__BEGIN_DECLS
/*
* Top level cert or CRL - the two are identical at this level - three
* components. The tbs field is saved in full DER form for sig verify.
*/
typedef struct {
DERItem tbs; /* sequence, DERTBSCert, DER_DEC_SAVE_DER */
DERItem sigAlg; /* sequence, DERAlgorithmId */
DERItem sig; /* bit string */
} DERSignedCertCrl;
/* DERItemSpecs to decode into a DERSignedCertCrl */
extern const DERItemSpec DERSignedCertCrlItemSpecs[];
extern const DERSize DERNumSignedCertCrlItemSpecs;
/* TBS cert components */
typedef struct {
DERItem version; /* integer, optional, EXPLICIT */
DERItem serialNum; /* integer */
DERItem tbsSigAlg; /* sequence, DERAlgorithmId */
DERItem issuer; /* sequence, TBD */
DERItem validity; /* sequence, DERValidity */
DERItem subject; /* sequence, TBD */
DERItem subjectPubKey; /* sequence, DERSubjPubKeyInfo */
DERItem issuerID; /* bit string, optional */
DERItem subjectID; /* bit string, optional */
DERItem extensions; /* sequence, optional, EXPLICIT */
} DERTBSCert;
/* DERItemSpecs to decode into a DERTBSCert */
extern const DERItemSpec DERTBSCertItemSpecs[];
extern const DERSize DERNumTBSCertItemSpecs;
/*
* validity - components can be either UTC or generalized time.
* Both are ASN_ANY with DER_DEC_SAVE_DER.
*/
typedef struct {
DERItem notBefore;
DERItem notAfter;
} DERValidity;
/* DERItemSpecs to decode into a DERValidity */
extern const DERItemSpec DERValidityItemSpecs[];
extern const DERSize DERNumValidityItemSpecs;
/* AttributeTypeAndValue components. */
typedef struct {
DERItem type;
DERItem value;
} DERAttributeTypeAndValue;
/* DERItemSpecs to decode into DERAttributeTypeAndValue */
extern const DERItemSpec DERAttributeTypeAndValueItemSpecs[];
extern const DERSize DERNumAttributeTypeAndValueItemSpecs;
/* Extension components */
typedef struct {
DERItem extnID;
DERItem critical;
DERItem extnValue;
} DERExtension;
/* DERItemSpecs to decode into DERExtension */
extern const DERItemSpec DERExtensionItemSpecs[];
extern const DERSize DERNumExtensionItemSpecs;
/* BasicConstraints components. */
typedef struct {
DERItem cA;
DERItem pathLenConstraint;
} DERBasicConstraints;
/* DERItemSpecs to decode into DERBasicConstraints */
extern const DERItemSpec DERBasicConstraintsItemSpecs[];
extern const DERSize DERNumBasicConstraintsItemSpecs;
/* PrivateKeyUsagePeriod components. */
typedef struct {
DERItem notBefore;
DERItem notAfter;
} DERPrivateKeyUsagePeriod;
/* DERItemSpecs to decode into a DERPrivateKeyUsagePeriod */
extern const DERItemSpec DERPrivateKeyUsagePeriodItemSpecs[];
extern const DERSize DERNumPrivateKeyUsagePeriodItemSpecs;
/* DistributionPoint components. */
typedef struct {
DERItem distributionPoint;
DERItem reasons;
DERItem cRLIssuer;
} DERDistributionPoint;
/* DERItemSpecs to decode into a DERDistributionPoint */
extern const DERItemSpec DERDistributionPointItemSpecs[];
extern const DERSize DERNumDistributionPointItemSpecs;
/* PolicyInformation components. */
typedef struct {
DERItem policyIdentifier;
DERItem policyQualifiers;
} DERPolicyInformation;
/* DERItemSpecs to decode into a DERPolicyInformation */
extern const DERItemSpec DERPolicyInformationItemSpecs[];
extern const DERSize DERNumPolicyInformationItemSpecs;
/* PolicyQualifierInfo components. */
typedef struct {
DERItem policyQualifierID;
DERItem qualifier;
} DERPolicyQualifierInfo;
/* DERItemSpecs to decode into a DERPolicyQualifierInfo */
extern const DERItemSpec DERPolicyQualifierInfoItemSpecs[];
extern const DERSize DERNumPolicyQualifierInfoItemSpecs;
/* UserNotice components. */
typedef struct {
DERItem noticeRef;
DERItem explicitText;
} DERUserNotice;
/* DERItemSpecs to decode into a DERUserNotice */
extern const DERItemSpec DERUserNoticeItemSpecs[];
extern const DERSize DERNumUserNoticeItemSpecs;
/* NoticeReference components. */
typedef struct {
DERItem organization;
DERItem noticeNumbers;
} DERNoticeReference;
/* DERItemSpecs to decode into a DERNoticeReference */
extern const DERItemSpec DERNoticeReferenceItemSpecs[];
extern const DERSize DERNumNoticeReferenceItemSpecs;
/* PolicyMapping components. */
typedef struct {
DERItem issuerDomainPolicy;
DERItem subjectDomainPolicy;
} DERPolicyMapping;
/* DERItemSpecs to decode into a DERPolicyMapping */
extern const DERItemSpec DERPolicyMappingItemSpecs[];
extern const DERSize DERNumPolicyMappingItemSpecs;
/* AccessDescription components. */
typedef struct {
DERItem accessMethod;
DERItem accessLocation;
} DERAccessDescription;
/* DERItemSpecs to decode into a DERAccessDescription */
extern const DERItemSpec DERAccessDescriptionItemSpecs[];
extern const DERSize DERNumAccessDescriptionItemSpecs;
/* AuthorityKeyIdentifier components. */
typedef struct {
DERItem keyIdentifier;
DERItem authorityCertIssuer;
DERItem authorityCertSerialNumber;
} DERAuthorityKeyIdentifier;
/* DERItemSpecs to decode into a DERAuthorityKeyIdentifier */
extern const DERItemSpec DERAuthorityKeyIdentifierItemSpecs[];
extern const DERSize DERNumAuthorityKeyIdentifierItemSpecs;
/* OtherName components. */
typedef struct {
DERItem typeIdentifier;
DERItem value;
} DEROtherName;
/* DERItemSpecs to decode into a DEROtherName */
extern const DERItemSpec DEROtherNameItemSpecs[];
extern const DERSize DERNumOtherNameItemSpecs;
/* PolicyConstraints components. */
typedef struct {
DERItem requireExplicitPolicy;
DERItem inhibitPolicyMapping;
} DERPolicyConstraints;
/* DERItemSpecs to decode into a DERPolicyConstraints */
extern const DERItemSpec DERPolicyConstraintsItemSpecs[];
extern const DERSize DERNumPolicyConstraintsItemSpecs;
/* TBS CRL */
typedef struct {
DERItem version; /* integer, optional */
DERItem tbsSigAlg; /* sequence, DERAlgorithmId */
DERItem issuer; /* sequence, TBD */
DERItem thisUpdate; /* ASN_ANY, SAVE_DER */
DERItem nextUpdate; /* ASN_ANY, SAVE_DER */
DERItem revokedCerts; /* sequence of DERRevokedCert, optional */
DERItem extensions; /* sequence, optional, EXPLICIT */
} DERTBSCrl;
/* DERItemSpecs to decode into a DERTBSCrl */
extern const DERItemSpec DERTBSCrlItemSpecs[];
extern const DERSize DERNumTBSCrlItemSpecs;
typedef struct {
DERItem serialNum; /* integer */
DERItem revocationDate; /* time - ASN_ANY, SAVE_DER */
DERItem extensions; /* sequence, optional, EXPLICIT */
} DERRevokedCert;
/* DERItemSpecs to decode into a DERRevokedCert */
extern const DERItemSpec DERRevokedCertItemSpecs[];
extern const DERSize DERNumRevokedCertItemSpecs;
__END_DECLS
#endif /* _DER_CERT_CRL_H_ */
+645
View File
@@ -0,0 +1,645 @@
/*
* Copyright (c) 2005-2010 Apple Inc. All Rights Reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* DER_Decode.c - DER decoding routines
*/
#include <libDER/DER_Decode.h>
#include <libDER/asn1Types.h>
#include <libDER/libDER_config.h>
#ifndef DER_DECODE_ENABLE
#error Please define DER_DECODE_ENABLE.
#endif
#if DER_DECODE_ENABLE
#define DER_DECODE_DEBUG 0
#if DER_DECODE_DEBUG
#include <stdio.h>
#define derDecDbg(a) printf(a)
#define derDecDbg1(a, b) printf(a, b)
#define derDecDbg2(a, b, c) printf(a, b, c)
#define derDecDbg3(a, b, c, d) printf(a, b, c, d)
#else
#define derDecDbg(a)
#define derDecDbg1(a, b)
#define derDecDbg2(a, b, c)
#define derDecDbg3(a, b, c, d)
#endif /* DER_DECODE_DEBUG */
/*
* Basic decoding primitive. Only works with:
*
* -- definite length encoding
* -- one-byte tags (unless DER_MULTIBYTE_TAGS is defined)
* -- max content length fits in a DERSize
*
* No malloc or copy of the contents is performed; the returned
* content->content.data is a pointer into the incoming der data.
*/
DERReturn DERDecodeItem(
const DERItem *der, /* data to decode */
DERDecodedInfo *decoded) /* RETURNED */
{
return DERDecodeItemPartialBuffer(der, decoded, false);
}
/*
* Basic decoding primitive. Allows for decoding with a partial buffer.
* if allowPartialBuffer is true. A partial buffer would normally fail
* because the encoded length would be greater than the size of the buffer passed in.
* Only works with:
*
* -- definite length encoding
* -- one-byte tags (unless DER_MULTIBYTE_TAGS is defined)
* -- max content length fits in a DERSize
*
* No malloc or copy of the contents is performed; the returned
* content->content.data is a pointer into the incoming der data.
*/
DERReturn DERDecodeItemPartialBuffer(
const DERItem *der, /* data to decode */
DERDecodedInfo *decoded, /* RETURNED */
bool allowPartialBuffer)
{
DERByte tag1; /* first tag byte */
DERByte len1; /* first length byte */
DERTag tagNumber; /* tag number without class and method bits */
DERByte *derPtr = der->data;
DERSize derLen = der->length;
/* The tag decoding below is fully BER complient. We support a max tag
value of 2 ^ ((sizeof(DERTag) * 8) - 3) - 1 so for tag size 1 byte we
support tag values from 0 - 0x1F. For tag size 2 tag values
from 0 - 0x1FFF and for tag size 4 values from 0 - 0x1FFFFFFF. */
if(derLen < 2) {
return DR_DecodeError;
}
/* Grab the first byte of the tag. */
tag1 = *derPtr++;
derLen--;
tagNumber = tag1 & 0x1F;
if(tagNumber == 0x1F) {
#ifdef DER_MULTIBYTE_TAGS
/* Long tag form: bit 8 of each octet shall be set to one unless it is
the last octet of the tag */
const DERTag overflowMask = ((DERTag)0x7F << (sizeof(DERTag) * 8 - 7));
DERByte tagByte;
tagNumber = 0;
if (*derPtr == 0x80 || *derPtr < 0x1F)
return DR_DecodeError;
do {
if(derLen < 2 || (tagNumber & overflowMask) != 0) {
return DR_DecodeError;
}
tagByte = *derPtr++;
derLen--;
tagNumber = (tagNumber << 7) | (tagByte & 0x7F);
} while((tagByte & 0x80) != 0);
/* Check for any of the top 3 reserved bits being set. */
if ((tagNumber & (overflowMask << 4)) != 0)
#endif
return DR_DecodeError;
}
/* Returned tag, top 3 bits are class/method remaining bits are number. */
decoded->tag = ((DERTag)(tag1 & 0xE0) << ((sizeof(DERTag) - 1) * 8)) | tagNumber;
/* Tag decoding above ensured we have at least one more input byte left. */
len1 = *derPtr++;
derLen--;
if(len1 & 0x80) {
/* long length form - first byte is length of length */
DERSize longLen = 0; /* long form length */
unsigned dex;
len1 &= 0x7f;
if((len1 > sizeof(DERSize)) || (len1 > derLen) || len1 == 0 || *derPtr == 0) {
/* no can do */
return DR_DecodeError;
}
for(dex=0; dex<len1; dex++) {
longLen <<= 8;
longLen |= *derPtr++;
derLen--;
}
if(longLen > derLen && !allowPartialBuffer) {
/* not enough data left for this encoding */
return DR_DecodeError;
}
decoded->content.data = derPtr;
decoded->content.length = longLen;
}
else {
/* short length form, len1 is the length */
if(len1 > derLen && !allowPartialBuffer) {
/* not enough data left for this encoding */
return DR_DecodeError;
}
decoded->content.data = derPtr;
decoded->content.length = len1;
}
return DR_Success;
}
/*
* Given a BIT_STRING, in the form of its raw content bytes,
* obtain the number of unused bits and the raw bit string bytes.
*/
DERReturn DERParseBitString(
const DERItem *contents,
DERItem *bitStringBytes, /* RETURNED */
DERByte *numUnusedBits) /* RETURNED */
{
if(contents->length < 2) {
/* not enough room for actual bits after the unused bits field */
*numUnusedBits = 0;
bitStringBytes->data = NULL;
bitStringBytes->length = 0;
return DR_Success;
}
*numUnusedBits = contents->data[0];
bitStringBytes->data = contents->data + 1;
bitStringBytes->length = contents->length - 1;
return DR_Success;
}
/*
* Given a BOOLEAN, in the form of its raw content bytes,
* obtain it's value.
*/
DERReturn DERParseBoolean(
const DERItem *contents,
bool *value) { /* RETURNED */
if (contents->length != 1 ||
(contents->data[0] != 0 && contents->data[0] != 0xFF))
return DR_DecodeError;
*value = contents->data[0] != 0;
return DR_Success;
}
/*
* Given a BOOLEAN, in the form of its raw content bytes,
* obtain it's value.
*/
DERReturn DERParseBooleanWithDefault(
const DERItem *contents,
bool defaultValue,
bool *value) { /* RETURNED */
if (contents->length == 0) {
*value = defaultValue;
return DR_Success;
}
return DERParseBoolean(contents, value);
}
DERReturn DERParseInteger(
const DERItem *contents,
uint32_t *result) { /* RETURNED */
uint64_t value;
DERReturn drtn = DERParseInteger64(contents, &value);
if (drtn == DR_Success) {
if (value > UINT32_MAX)
drtn = DR_BufOverflow;
else
*result = (uint32_t)value;
}
return drtn;
}
DERReturn DERParseInteger64(
const DERItem *contents,
uint64_t *result) { /* RETURNED */
DERSize ix, length = contents->length;
if (length == 0)
return DR_DecodeError;
if (contents->data[0] & 0x80)
return DR_DecodeError;
if (contents->data[0] == 0) {
if (length > 1 && (contents->data[1] & 0x80) == 0)
return DR_DecodeError;
if (length > sizeof(*result) + 1)
return DR_BufOverflow;
} else if (length > sizeof(*result)) {
return DR_BufOverflow;
}
uint64_t value = 0;
for (ix = 0; ix < length; ++ix) {
value <<= 8;
value += contents->data[ix];
}
*result = value;
return DR_Success;
}
/* Sequence/set support */
/*
* To decode a set or sequence, call DERDecodeSeqInit once, then
* call DERDecodeSeqNext to get each enclosed item.
* DERDecodeSeqNext returns DR_EndOfSequence when no more
* items are available.
*/
DERReturn DERDecodeSeqInit(
const DERItem *der, /* data to decode */
DERTag *tag, /* RETURNED tag of sequence/set. This will be
* either ASN1_CONSTR_SEQUENCE or ASN1_CONSTR_SET. */
DERSequence *derSeq) /* RETURNED, to use in DERDecodeSeqNext */
{
DERDecodedInfo decoded;
DERReturn drtn;
drtn = DERDecodeItem(der, &decoded);
if(drtn) {
return drtn;
}
*tag = decoded.tag;
switch(decoded.tag) {
case ASN1_CONSTR_SEQUENCE:
case ASN1_CONSTR_SET:
break;
default:
return DR_UnexpectedTag;
}
derSeq->nextItem = decoded.content.data;
derSeq->end = decoded.content.data + decoded.content.length;
return DR_Success;
}
/*
* Use this to start in on decoding a sequence's content, when
* the top-level tag and content have already been decoded.
*/
DERReturn DERDecodeSeqContentInit(
const DERItem *content,
DERSequence *derSeq) /* RETURNED, to use in DERDecodeSeqNext */
{
/* just prepare for decoding items in content */
derSeq->nextItem = content->data;
derSeq->end = content->data + content->length;
return DR_Success;
}
DERReturn DERDecodeSeqNext(
DERSequence *derSeq,
DERDecodedInfo *decoded) /* RETURNED */
{
DERReturn drtn;
DERItem item;
if(derSeq->nextItem >= derSeq->end) {
/* normal termination, contents all used up */
return DR_EndOfSequence;
}
/* decode next item */
item.data = derSeq->nextItem;
item.length = (DERSize)(derSeq->end - derSeq->nextItem);
drtn = DERDecodeItem(&item, decoded);
if(drtn) {
return drtn;
}
/* skip over the item we just decoded */
derSeq->nextItem = decoded->content.data + decoded->content.length;
return DR_Success;
}
/*
* High level sequence parse, starting with top-level tag and content.
* Top level tag must be ASN1_CONSTR_SEQUENCE - if it's not, and that's
* OK, use DERParseSequenceContent().
*/
DERReturn DERParseSequence(
const DERItem *der,
DERShort numItems, /* size of itemSpecs[] */
const DERItemSpec *itemSpecs,
void *dest, /* DERDecodedInfo(s) here RETURNED */
DERSize sizeToZero) /* optional */
{
DERReturn drtn;
DERDecodedInfo topDecode;
drtn = DERDecodeItem(der, &topDecode);
if(drtn) {
return drtn;
}
if(topDecode.tag != ASN1_CONSTR_SEQUENCE) {
return DR_UnexpectedTag;
}
return DERParseSequenceContent(&topDecode.content,
numItems, itemSpecs, dest, sizeToZero);
}
/* high level sequence parse, starting with sequence's content */
DERReturn DERParseSequenceContent(
const DERItem *content,
DERShort numItems, /* size of itemSpecs[] */
const DERItemSpec *itemSpecs,
void *dest, /* DERDecodedInfo(s) here RETURNED */
DERSize sizeToZero) /* optional */
{
DERSequence derSeq;
DERReturn drtn;
DERShort itemDex;
DERByte *currDER; /* full DER encoding of current item */
if(sizeToZero) {
DERMemset(dest, 0, sizeToZero);
}
drtn = DERDecodeSeqContentInit(content, &derSeq);
if(drtn) {
return drtn;
}
/* main loop */
for(itemDex=0 ; itemDex<numItems; ) {
DERDecodedInfo currDecoded;
DERShort i;
DERTag foundTag;
char foundMatch = 0;
/* save this in case of DER_DEC_SAVE_DER */
currDER = derSeq.nextItem;
drtn = DERDecodeSeqNext(&derSeq, &currDecoded);
if(drtn) {
/*
* One legal error here is DR_EndOfSequence when
* all remaining DERSequenceItems are optional.
*/
if(drtn == DR_EndOfSequence) {
for(i=itemDex; i<numItems; i++) {
if(!(itemSpecs[i].options & DER_DEC_OPTIONAL)) {
/* unexpected end of sequence */
return DR_IncompleteSeq;
}
}
/* the rest are optional; success */
return DR_Success;
}
else {
/* any other error is fatal */
return drtn;
}
} /* decode error */
/*
* Seek matching tag or ASN_ANY in itemSpecs, skipping
* over optional items.
*/
foundTag = currDecoded.tag;
derDecDbg1("--- foundTag 0x%llx\n", foundTag);
for(i=itemDex; i<numItems; i++) {
const DERItemSpec *currItemSpec = &itemSpecs[i];
DERShort currOptions = currItemSpec->options;
derDecDbg3("--- currItem %u expectTag 0x%llx currOptions 0x%x\n",
i, currItemSpec->tag, currOptions);
if((currOptions & DER_DEC_ASN_ANY) ||
(foundTag == currItemSpec->tag)) {
/*
* We're good with this one. Cook up destination address
* as appropriate.
*/
if(!(currOptions & DER_DEC_SKIP)) {
derDecDbg1("--- MATCH at currItem %u\n", i);
DERByte *byteDst = (DERByte *)dest + currItemSpec->offset;
DERItem *dst = (DERItem *)byteDst;
*dst = currDecoded.content;
if(currOptions & DER_DEC_SAVE_DER) {
/* recreate full DER encoding of this item */
derDecDbg1("--- SAVE_DER at currItem %u\n", i);
dst->data = currDER;
dst->length += (currDecoded.content.data - currDER);
}
}
/* on to next item */
itemDex = i + 1;
/* is this the end? */
if(itemDex == numItems) {
/* normal termination if we consumed everything */
if (derSeq.nextItem == derSeq.end)
return DR_Success;
else
return DR_DecodeError;
}
else {
/* on to next item */
foundMatch = 1;
break;
}
} /* ASN_ANY, or match */
/*
* If current itemSpec isn't optional, abort - else on to
* next item
*/
if(!(currOptions & DER_DEC_OPTIONAL)) {
derDecDbg1("--- MISMATCH at currItem %u, !OPTIONAL, abort\n", i);
return DR_UnexpectedTag;
}
/* else this was optional, on to next item */
} /* searching for tag match */
if(foundMatch == 0) {
/*
* Found an item we couldn't match to any tag spec and we're at
* the end.
*/
derDecDbg("--- TAG NOT FOUND, abort\n");
return DR_UnexpectedTag;
}
/* else on to next item */
} /* main loop */
/* Template has 0 items if we get here. */
/* normal termination if we consumed everything, (the sequence was empty) */
if (derSeq.nextItem == derSeq.end)
return DR_Success;
else
return DR_DecodeError;
}
#if 0
/*
* High level sequence parse, starting with top-level tag and content.
* Top level tag must be ASN1_CONSTR_SEQUENCE - if it's not, and that's
* OK, use DERParseSequenceContent().
*/
DERReturn DERParseSequenceOf(
const DERItem *der,
DERShort numItems, /* size of itemSpecs[] */
const DERItemSpec *itemSpecs,
void *dest, /* DERDecodedInfo(s) here RETURNED */
DERSize *numDestItems) /* output */
{
DERReturn drtn;
DERDecodedInfo topDecode;
drtn = DERDecodeItem(der, &topDecode);
if(drtn) {
return drtn;
}
if(topDecode.tag != ASN1_CONSTR_SEQUENCE) {
return DR_UnexpectedTag;
}
return DERParseSequenceContent(&topDecode.content,
numItems, itemSpecs, dest, sizeToZero);
}
/*
* High level set of parse, starting with top-level tag and content.
* Top level tag must be ASN1_CONSTR_SET - if it's not, and that's
* OK, use DERParseSetOrSequenceOfContent().
*/
DERReturn DERParseSetOf(
const DERItem *der,
DERShort numItems, /* size of itemSpecs[] */
const DERItemSpec *itemSpecs,
void *dest, /* DERDecodedInfo(s) here RETURNED */
DERSize *numDestItems) /* output */
{
DERReturn drtn;
DERDecodedInfo topDecode;
drtn = DERDecodeItem(der, &topDecode);
if(drtn) {
return drtn;
}
if(topDecode.tag != ASN1_CONSTR_SET) {
return DR_UnexpectedTag;
}
return DERParseSetOrSequenceOfContent(&topDecode.content,
numItems, itemSpecs, dest, numDestItems);
}
/* High level set of or sequence of parse, starting with set or
sequence's content */
DERReturn DERParseSetOrSequenceOfContent(
const DERItem *content,
void(*itemHandeler)(void *, const DERDecodedInfo *)
void *itemHandelerContext);
{
DERSequence derSeq;
DERShort itemDex;
drtn = DERDecodeSeqContentInit(content, &derSeq);
require_noerr_quiet(drtn, badCert);
/* main loop */
for (;;) {
DERDecodedInfo currDecoded;
DERShort i;
DERByte foundTag;
char foundMatch = 0;
drtn = DERDecodeSeqNext(&derSeq, &currDecoded);
if(drtn) {
/* The only legal error here is DR_EndOfSequence. */
if(drtn == DR_EndOfSequence) {
/* no more items left in the sequence; success */
return DR_Success;
}
else {
/* any other error is fatal */
require_noerr_quiet(drtn, badCert);
}
} /* decode error */
/* Each element can be anything. */
foundTag = currDecoded.tag;
/*
* We're good with this one. Cook up destination address
* as appropriate.
*/
DERByte *byteDst = (DERByte *)dest + currItemSpec->offset;
DERItem *dst = (DERItem *)byteDst;
*dst = currDecoded.content;
if(currOptions & DER_DEC_SAVE_DER) {
/* recreate full DER encoding of this item */
derDecDbg1("--- SAVE_DER at currItem %u\n", i);
dst->data = currDER;
dst->length += (currDecoded.content.data - currDER);
}
/* on to next item */
itemDex = i + 1;
/* is this the end? */
if(itemDex == numItems) {
/* normal termination */
return DR_Success;
}
else {
/* on to next item */
foundMatch = 1;
break;
}
/*
* If current itemSpec isn't optional, abort - else on to
* next item
*/
if(!(currOptions & DER_DEC_OPTIONAL)) {
derDecDbg1("--- MISMATCH at currItem %u, !OPTIONAL, abort\n", i);
return DR_UnexpectedTag;
}
/* else this was optional, on to next item */
} /* searching for tag match */
if(foundMatch == 0) {
/*
* Found an item we couldn't match to any tag spec and we're at
* the end.
*/
derDecDbg("--- TAG NOT FOUND, abort\n");
return DR_UnexpectedTag;
}
/* else on to next item */
} /* main loop */
/*
* If we get here, there appears to be more to process, but we've
* given the caller everything they want.
*/
return DR_Success;
}
}
#endif
#endif /* DER_DECODE_ENABLE */
+219
View File
@@ -0,0 +1,219 @@
/*
* Copyright (c) 2005-2010 Apple Inc. All Rights Reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* DER_Decode.h - DER decoding routines
*/
#ifndef _DER_DECODE_H_
#define _DER_DECODE_H_
#include <libDER/libDER.h>
#include <stdbool.h>
__BEGIN_DECLS
/*
* Decoding one item consists of extracting its tag, a pointer
* to the actual content, and the length of the content. Those
* three are represented by a DERDecodedInfo.
*/
typedef struct {
DERTag tag;
DERItem content;
} DERDecodedInfo;
/*
* Basic decoding primitive. Only works with:
*
* -- definite length encoding
* -- one-byte tags
* -- max content length fits in a DERSize
*
* No malloc or copy of the contents is performed; the returned
* content->content.data is a pointer into the incoming der data.
*/
DERReturn DERDecodeItem(
const DERItem *der, /* data to decode */
DERDecodedInfo *decoded); /* RETURNED */
/*
* Basic decoding primitive. Allows for decoding with a partial buffer.
* if allowPartialBuffer is true. A partial buffer would normally fail
* because the encoded length would be greater than the size of the buffer passed in.
* Only works with:
*
* -- definite length encoding
* -- one-byte tags (unless DER_MULTIBYTE_TAGS is defined)
* -- max content length fits in a DERSize
*
* No malloc or copy of the contents is performed; the returned
* content->content.data is a pointer into the incoming der data.
*/
DERReturn DERDecodeItemPartialBuffer(
const DERItem *der, /* data to decode */
DERDecodedInfo *decoded, /* RETURNED */
bool allowPartialBuffer);
/*
* Given a BIT_STRING, in the form of its raw content bytes,
* obtain the number of unused bits and the raw bit string bytes.
*/
DERReturn DERParseBitString(
const DERItem *contents,
DERItem *bitStringBytes, /* RETURNED */
DERByte *numUnusedBits); /* RETURNED */
/*
* Given a BOOLEAN, in the form of its raw content bytes,
* obtain it's value.
*/
DERReturn DERParseBoolean(
const DERItem *contents,
bool *value); /* RETURNED */
DERReturn DERParseBooleanWithDefault(
const DERItem *contents,
bool defaultValue,
bool *value); /* RETURNED */
/*
* Given a positive INTEGER, in the form of its raw content bytes,
* obtain it's value as a 32 bit or 64 bit quantity.
* Returns DR_BufOverflow if the value is too large to fit in the return type
*/
DERReturn DERParseInteger(
const DERItem *contents,
uint32_t *value); /* RETURNED */
DERReturn DERParseInteger64(
const DERItem *contents,
uint64_t *value); /* RETURNED */
/*
* Sequence/set decode support.
*/
/* state representing a sequence or set being decoded */
typedef struct {
DERByte *nextItem;
DERByte *end;
} DERSequence;
/*
* To decode a set or sequence, call DERDecodeSeqInit or
* DERDecodeSeqContentInit once, then call DERDecodeSeqNext to
* get each enclosed item.
*
* DERDecodeSeqNext returns DR_EndOfSequence when no more
* items are available.
*/
/*
* Use this to parse the top level sequence's tag and content length.
*/
DERReturn DERDecodeSeqInit(
const DERItem *der, /* data to decode */
DERTag *tag, /* RETURNED tag of sequence/set. This will be
* either ASN1_CONSTR_SEQUENCE or
* ASN1_CONSTR_SET. */
DERSequence *derSeq); /* RETURNED, to use in DERDecodeSeqNext */
/*
* Use this to start in on decoding a sequence's content, when
* the top-level tag and content have already been decoded.
*/
DERReturn DERDecodeSeqContentInit(
const DERItem *content,
DERSequence *derSeq); /* RETURNED, to use in DERDecodeSeqNext */
/* obtain the next decoded item in a sequence or set */
DERReturn DERDecodeSeqNext(
DERSequence *derSeq,
DERDecodedInfo *decoded); /* RETURNED */
/*
* High level sequence decode.
*/
/*
* Per-item decode options.
*/
/* Explicit default, no options */
#define DER_DEC_NO_OPTS 0x0000
/* This item optional, can be skipped during decode */
#define DER_DEC_OPTIONAL 0x0001
/* Skip the tag check; accept anything. */
#define DER_DEC_ASN_ANY 0x0002
/* Skip item, no write to DERDecodedInfo (but tag check still performed) */
#define DER_DEC_SKIP 0x0004
/* Save full DER encoding in DERDecodedInfo, including tag and length. Normally
* only the content is saved. */
#define DER_DEC_SAVE_DER 0x0008
/*
* High level sequence parse, starting with top-level tag and content.
* Top level tag must be ASN1_CONSTR_SEQUENCE - if it's not, and that's
* OK, use DERParseSequenceContent().
*
* These never return DR_EndOfSequence - if an *unexpected* end of sequence
* occurs, return DR_IncompleteSeq.
*
* Results of the decoding of one item are placed in a DERItem whose address
* is the dest arg plus the offset value in the associated DERItemSpec.
*
* Items which are optional (DER_DEC_OPTIONAL) and which are not found,
* leave their associated DERDecodedInfos unmodified.
*
* Processing of a sequence ends on detection of any error or after the
* last DERItemSpec is processed.
*
* The sizeToZero argument, if nonzero, indicates the number of bytes
* starting at dest to zero before processing the sequence. This is
* generally desirable, particularly if there are any DER_DEC_OPTIONAL
* items in the sequence; skipped optional items are detected by the
* caller via a NULL DERDecodedInfo.content.data; if this hasn't been
* explicitly zeroed (generally, by passing a nonzero value of sizeToZero),
* skipped items can't be detected.
*/
DERReturn DERParseSequence(
const DERItem *der,
DERShort numItems, /* size of itemSpecs[] */
const DERItemSpec *itemSpecs,
void *dest, /* DERDecodedInfo(s) here RETURNED */
DERSize sizeToZero); /* optional */
/* high level sequence parse, starting with sequence's content */
DERReturn DERParseSequenceContent(
const DERItem *content,
DERShort numItems, /* size of itemSpecs[] */
const DERItemSpec *itemSpecs,
void *dest, /* DERDecodedInfo(s) here RETURNED */
DERSize sizeToZero); /* optional */
__END_DECLS
#endif /* _DER_DECODE_H_ */
+162
View File
@@ -0,0 +1,162 @@
/* Copyright (c) 2005-2008,2010 Apple Inc. All Rights Reserved. */
/*
* DER_Digest.h - DER encode a DigestInfo
*
* Created Nov. 9 2005 by dmitch
*/
#include <libDER/DER_Digest.h>
/*
* Create an encoded DigestInfo based on the specified SHA1 digest.
* The digest must be 20 bytes long.
*
* Result is placed in caller's buffer, which must be at least of
* length DER_DIGEST_INFO_LEN bytes.
*
* The *resultLen parameter is the available size in the result
* buffer on input, and the actual length of the encoded DigestInfo
* on output.
*
* In the interest of saving code space, this just drops the caller's
* digest into an otherwise hard-coded, fixed, encoded SHA1 DigestInfo.
* Nothing is variable so we know the whole thing. It looks like this:
*
* SEQUENCE OF <33> {
* SEQUENCE OF <9> {
* OID <5>: OID : < 06 05 2B 0E 03 02 1A >
* NULL
* }
* OCTET STRING <20>:
* 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55
* 55 55 55 55
* }
*
*
* tower.local:digestInfo> hexdump -x /tmp/encodedDigest
* 0000000 3021 3009 0605 2b0e 0302 1a05 0004 1455
* 0000010 5555 5555 5555 5555 5555 5555 5555 5555
* *
* 0000020
*/
static const unsigned char encodedSha1Digest[] =
{
0x30, 0x21, /* top level sequence length 33 */
0x30, 0x09, /* algorithm ID, sequence length 9 */
0x06, 0x05, /* alg OID, length 5, SHA1 */
0x2b, 0x0e, 0x03, 0x02, 0x1a,
0x05, 0x00, /* NULL parameters */
0x04, 0x14 /* integer length 20 */
/* digest follows */
};
DERReturn DEREncodeSHA1DigestInfo(
const DERByte *sha1Digest,
DERSize sha1DigestLen,
DERByte *result, /* encoded result RETURNED here */
DERSize *resultLen) /* IN/OUT */
{
DERSize totalLen = sizeof(encodedSha1Digest) + DER_SHA1_DIGEST_LEN;
if((sha1Digest == NULL) || (sha1DigestLen != DER_SHA1_DIGEST_LEN) ||
(result == NULL) || (resultLen == NULL)) {
return DR_ParamErr;
}
if(*resultLen < DER_SHA1_DIGEST_INFO_LEN) {
return DR_BufOverflow;
}
DERMemmove(result, encodedSha1Digest, sizeof(encodedSha1Digest));
DERMemmove(result + sizeof(encodedSha1Digest), sha1Digest, DER_SHA1_DIGEST_LEN);
*resultLen = totalLen;
return DR_Success;
}
/*
joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)
csor(3) nistalgorithm(4) hashAlgs(2) sha256(1)
future ones to add: sha384(2) sha512(3) sha224(4)
*/
static const unsigned char encodedSha256Digest[] =
{
0x30, 0x31, /* top level sequence length 49 */
0x30, 0x0d, /* algorithm ID, sequence length 13 */
0x06, 0x09,
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
0x05, 0x00, /* NULL parameters */
0x04, 0x20 /* integer length 32 */
/* digest follows */
};
DERReturn DEREncodeSHA256DigestInfo(
const DERByte *sha256Digest,
DERSize sha256DigestLen,
DERByte *result, /* encoded result RETURNED here */
DERSize *resultLen) /* IN/OUT */
{
DERSize totalLen = sizeof(encodedSha256Digest) + DER_SHA256_DIGEST_LEN;
if((sha256Digest == NULL) || (sha256DigestLen != DER_SHA256_DIGEST_LEN) ||
(result == NULL) || (resultLen == NULL)) {
return DR_ParamErr;
}
if(*resultLen < DER_SHA256_DIGEST_INFO_LEN) {
return DR_BufOverflow;
}
DERMemmove(result, encodedSha256Digest, sizeof(encodedSha256Digest));
DERMemmove(result + sizeof(encodedSha256Digest), sha256Digest, DER_SHA256_DIGEST_LEN);
*resultLen = totalLen;
return DR_Success;
}
/* Same thing, MD5/MD2 */
static const unsigned char encodedMdDigest[] =
{
0x30, 0x20, /* top level sequence length 32 */
0x30, 0x0c, /* algorithm ID, sequence length 12 */
0x06, 0x08, /* alg OID, length 8, MD2/MD5 */
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02,
0x05, /* 5 = MD5, 2 = MD2 */
0x05, 0x00, /* NULL parameters */
0x04, 0x10 /* integer length 16 */
/* digest follows */
};
#define WHICH_DIGEST_INDEX 13
#define WHICH_DIGEST_MD2 2
#define WHICH_DIGEST_MD5 5
DERReturn DEREncodeMDDigestInfo(
WhichDigest whichDigest,
const DERByte *mdDigest,
DERSize mdDigestLen,
DERByte *result, /* encoded result RETURNED here */
DERSize *resultLen) /* IN/OUT */
{
DERSize totalLen = sizeof(encodedMdDigest) + DER_MD_DIGEST_LEN;
if((mdDigest == NULL) || (mdDigestLen != DER_MD_DIGEST_LEN) ||
(result == NULL) || (resultLen == NULL)) {
return DR_ParamErr;
}
if(*resultLen < totalLen) {
return DR_BufOverflow;
}
DERMemmove(result, encodedMdDigest, sizeof(encodedMdDigest));
DERMemmove(result + sizeof(encodedMdDigest), mdDigest, DER_MD_DIGEST_LEN);
switch(whichDigest) {
case WD_MD2:
result[WHICH_DIGEST_INDEX] = WHICH_DIGEST_MD2;
break;
case WD_MD5:
result[WHICH_DIGEST_INDEX] = WHICH_DIGEST_MD5;
break;
default:
return DR_ParamErr;
}
*resultLen = totalLen;
return DR_Success;
}
+70
View File
@@ -0,0 +1,70 @@
/* Copyright (c) 2005-2008,2010 Apple Inc. All Rights Reserved. */
/*
* DER_Digest.h - DER encode a DigestInfo
*
* Created Nov. 9 2005 by dmitch
*/
#ifndef _DER_DIGEST_H_
#define _DER_DIGEST_H_
#include <libDER/libDER.h>
__BEGIN_DECLS
/*
* Create an encoded DigestInfo based on the specified SHA1 digest.
* The incoming digest must be 20 bytes long.
*
* Result is placed in caller's buffer, which must be at least of
* length DER_SHA1_DIGEST_INFO_LEN bytes.
*
* The *resultLen parameter is the available size in the result
* buffer on input, and the actual length of the encoded DigestInfo
* on output.
*/
#define DER_SHA1_DIGEST_LEN 20
#define DER_SHA1_DIGEST_INFO_LEN 35
DERReturn DEREncodeSHA1DigestInfo(
const DERByte *sha1Digest,
DERSize sha1DigestLen,
DERByte *result, /* encoded result RETURNED here */
DERSize *resultLen); /* IN/OUT */
#define DER_SHA256_DIGEST_LEN 32
#define DER_SHA256_DIGEST_INFO_LEN 51
DERReturn DEREncodeSHA256DigestInfo(
const DERByte *sha256Digest,
DERSize sha256DigestLen,
DERByte *result, /* encoded result RETURNED here */
DERSize *resultLen); /* IN/OUT */
/*
* Likewise, create an encoded DIgestInfo for specified MD5 or MD2 digest.
*/
#define DER_MD_DIGEST_LEN 16
#define DER_MD_DIGEST_INFO_LEN 34
typedef enum {
WD_MD2 = 1,
WD_MD5 = 2
} WhichDigest;
DERReturn DEREncodeMDDigestInfo(
WhichDigest whichDigest,
const DERByte *mdDigest,
DERSize mdDigestLen,
DERByte *result, /* encoded result RETURNED here */
DERSize *resultLen); /* IN/OUT */
/* max sizes you'll need in the general cases */
#define DER_MAX_DIGEST_LEN DER_SHA256_DIGEST_LEN
#define DER_MAX_ENCODED_INFO_LEN DER_SHA256_DIGEST_INFO_LEN
__END_DECLS
#endif /* _DER_DIGEST_H_ */
+342
View File
@@ -0,0 +1,342 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* DER_Encode.h - DER encoding routines
*
* Created Dec. 2 2005 by dmitch
*/
#include <libDER/DER_Encode.h>
#include <libDER/asn1Types.h>
#include <libDER/libDER_config.h>
#include <libDER/DER_Decode.h>
#ifndef DER_ENCODE_ENABLE
#error Please define DER_ENCODE_ENABLE.
#endif
#if DER_ENCODE_ENABLE
/* calculate size of encoded tag */
static DERSize DERLengthOfTag(
DERTag tag)
{
DERSize rtn = 1;
tag &= ASN1_TAGNUM_MASK;
if (tag >= 0x1F) {
/* Shift 7-bit digits out of the tag integer until it's zero. */
while(tag != 0) {
rtn++;
tag >>= 7;
}
}
return rtn;
}
/* encode tag */
static DERReturn DEREncodeTag(
DERTag tag,
DERByte *buf, /* encoded length goes here */
DERSize *inOutLen) /* IN/OUT */
{
DERSize outLen = DERLengthOfTag(tag);
DERTag tagNumber = tag & ASN1_TAGNUM_MASK;
DERByte tag1 = (tag >> (sizeof(DERTag) * 8 - 8)) & 0xE0;
if(outLen > *inOutLen) {
return DR_BufOverflow;
}
if(outLen == 1) {
/* short form */
*buf = tag1 | tagNumber;
}
else {
/* long form */
DERByte *tagBytes = buf + outLen; // l.s. digit of tag
*buf = tag1 | 0x1F; // tag class / method indicator
*--tagBytes = tagNumber & 0x7F;
tagNumber >>= 7;
while(tagNumber != 0) {
*--tagBytes = (tagNumber & 0x7F) | 0x80;
tagNumber >>= 7;
}
}
*inOutLen = outLen;
return DR_Success;
}
/* calculate size of encoded length */
DERSize DERLengthOfLength(
DERSize length)
{
DERSize rtn;
if(length < 0x80) {
/* short form length */
return 1;
}
/* long form - one length-of-length byte plus length bytes */
rtn = 1;
while(length != 0) {
rtn++;
length >>= 8;
}
return rtn;
}
/* encode length */
DERReturn DEREncodeLength(
DERSize length,
DERByte *buf, /* encoded length goes here */
DERSize *inOutLen) /* IN/OUT */
{
DERByte *lenBytes;
DERSize outLen = DERLengthOfLength(length);
if(outLen > *inOutLen) {
return DR_BufOverflow;
}
if(length < 0x80) {
/* short form */
*buf = (DERByte)length;
*inOutLen = 1;
return DR_Success;
}
/* long form */
*buf = (outLen - 1) | 0x80; // length of length, long form indicator
lenBytes = buf + outLen - 1; // l.s. digit of length
while(length != 0) {
*lenBytes-- = (DERByte)length;
length >>= 8;
}
*inOutLen = outLen;
return DR_Success;
}
DERSize DERLengthOfItem(
DERTag tag,
DERSize length)
{
return DERLengthOfTag(tag) + DERLengthOfLength(length) + length;
}
DERReturn DEREncodeItem(
DERTag tag,
DERSize length,
const DERByte *src,
DERByte *derOut, /* encoded item goes here */
DERSize *inOutLen) /* IN/OUT */
{
DERReturn drtn;
DERSize itemLen;
DERByte *currPtr = derOut;
DERSize bytesLeft = DERLengthOfItem(tag, length);
if(bytesLeft > *inOutLen) {
return DR_BufOverflow;
}
*inOutLen = bytesLeft;
/* top level tag */
itemLen = bytesLeft;
drtn = DEREncodeTag(tag, currPtr, &itemLen);
if(drtn) {
return drtn;
}
currPtr += itemLen;
bytesLeft -= itemLen;
itemLen = bytesLeft;
drtn = DEREncodeLength(length, currPtr, &itemLen);
if(drtn) {
return drtn;
}
currPtr += itemLen;
bytesLeft -= itemLen;
DERMemmove(currPtr, src, length);
return DR_Success;
}
static /* calculate the content length of an encoded sequence */
DERSize DERContentLengthOfEncodedSequence(
const void *src, /* generally a ptr to a struct full of
* DERItems */
DERShort numItems, /* size of itemSpecs[] */
const DERItemSpec *itemSpecs)
{
DERSize contentLen = 0;
unsigned dex;
DERSize thisContentLen;
/* find length of each item */
for(dex=0; dex<numItems; dex++) {
const DERItemSpec *currItemSpec = &itemSpecs[dex];
DERShort currOptions = currItemSpec->options;
const DERByte *byteSrc = (const DERByte *)src + currItemSpec->offset;
const DERItem *itemSrc = (const DERItem *)byteSrc;
if(currOptions & DER_ENC_WRITE_DER) {
/* easy case - no encode */
contentLen += itemSrc->length;
continue;
}
if ((currOptions & DER_DEC_OPTIONAL) && itemSrc->length == 0) {
/* If an optional item isn't present we don't encode a
tag and len. */
continue;
}
/*
* length of this item =
* tag (one byte) +
* length of length +
* content length +
* optional zero byte for signed integer
*/
contentLen += DERLengthOfTag(currItemSpec->tag);
/* check need for pad byte before calculating lengthOfLength... */
thisContentLen = itemSrc->length;
if((currOptions & DER_ENC_SIGNED_INT) &&
(itemSrc->length != 0)) {
if(itemSrc->data[0] & 0x80) {
/* insert zero keep it positive */
thisContentLen++;
}
}
contentLen += DERLengthOfLength(thisContentLen);
contentLen += thisContentLen;
}
return contentLen;
}
DERReturn DEREncodeSequence(
DERTag topTag, /* ASN1_CONSTR_SEQUENCE, ASN1_CONSTR_SET */
const void *src, /* generally a ptr to a struct full of
* DERItems */
DERShort numItems, /* size of itemSpecs[] */
const DERItemSpec *itemSpecs,
DERByte *derOut, /* encoded data written here */
DERSize *inOutLen) /* IN/OUT */
{
const DERByte *endPtr = derOut + *inOutLen;
DERByte *currPtr = derOut;
DERSize bytesLeft = *inOutLen;
DERSize contentLen;
DERReturn drtn;
DERSize itemLen;
unsigned dex;
/* top level tag */
itemLen = bytesLeft;
drtn = DEREncodeTag(topTag, currPtr, &itemLen);
if(drtn) {
return drtn;
}
currPtr += itemLen;
bytesLeft -= itemLen;
if(currPtr >= endPtr) {
return DR_BufOverflow;
}
/* content length */
contentLen = DERContentLengthOfEncodedSequence(src, numItems, itemSpecs);
itemLen = bytesLeft;
drtn = DEREncodeLength(contentLen, currPtr, &itemLen);
if(drtn) {
return drtn;
}
currPtr += itemLen;
bytesLeft -= itemLen;
if(currPtr + contentLen > endPtr) {
return DR_BufOverflow;
}
/* we don't have to check for overflow any more */
/* grind thru the items */
for(dex=0; dex<numItems; dex++) {
const DERItemSpec *currItemSpec = &itemSpecs[dex];
DERShort currOptions = currItemSpec->options;
const DERByte *byteSrc = (const DERByte *)src + currItemSpec->offset;
const DERItem *itemSrc = (const DERItem *)byteSrc;
int prependZero = 0;
if(currOptions & DER_ENC_WRITE_DER) {
/* easy case */
DERMemmove(currPtr, itemSrc->data, itemSrc->length);
currPtr += itemSrc->length;
bytesLeft -= itemSrc->length;
continue;
}
if ((currOptions & DER_DEC_OPTIONAL) && itemSrc->length == 0) {
/* If an optional item isn't present we skip it. */
continue;
}
/* encode one item: first the tag */
itemLen = bytesLeft;
drtn = DEREncodeTag(currItemSpec->tag, currPtr, &itemLen);
if(drtn) {
return drtn;
}
currPtr += itemLen;
bytesLeft -= itemLen;
/* do we need to prepend a zero to content? */
contentLen = itemSrc->length;
if((currOptions & DER_ENC_SIGNED_INT) &&
(itemSrc->length != 0)) {
if(itemSrc->data[0] & 0x80) {
/* insert zero keep it positive */
contentLen++;
prependZero = 1;
}
}
/* encode content length */
itemLen = bytesLeft;
drtn = DEREncodeLength(contentLen, currPtr, &itemLen);
if(drtn) {
return drtn;
}
currPtr += itemLen;
bytesLeft -= itemLen;
/* now the content, with possible leading zero added */
if(prependZero) {
*currPtr++ = 0;
bytesLeft--;
}
DERMemmove(currPtr, itemSrc->data, itemSrc->length);
currPtr += itemSrc->length;
bytesLeft -= itemSrc->length;
}
*inOutLen = (DERSize)(currPtr - derOut);
return DR_Success;
}
/* calculate the length of an encoded sequence. */
DERSize DERLengthOfEncodedSequence(
DERTag topTag,
const void *src, /* generally a ptr to a struct full of
* DERItems */
DERShort numItems, /* size of itemSpecs[] */
const DERItemSpec *itemSpecs)
{
DERSize contentLen = DERContentLengthOfEncodedSequence(
src, numItems, itemSpecs);
return DERLengthOfTag(topTag) +
DERLengthOfLength(contentLen) +
contentLen;
}
#endif /* DER_ENCODE_ENABLE */
+98
View File
@@ -0,0 +1,98 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* DER_Encode.h - DER encoding routines
*
* Created Dec. 2 2005 by dmitch
*/
#ifndef _DER_ENCODE_H_
#define _DER_ENCODE_H_
#include <libDER/libDER.h>
__BEGIN_DECLS
/*
* Max size of an encoded item given its length.
* This includes a possible leading zero prepended to a signed integer
* (see DER_ENC_SIGNED_INT below).
*/
#define DER_MAX_ENCODED_SIZE(len) \
( 1 + /* tag */ \
5 + /* max length */ \
1 + /* possible prepended zero */ \
len)
/* calculate size of encoded length */
DERSize DERLengthOfLength(
DERSize length);
/* encode length */
DERReturn DEREncodeLength(
DERSize length,
DERByte *buf, /* encoded length goes here */
DERSize *inOutLen); /* IN/OUT */
/* calculate size of encoded length */
DERSize DERLengthOfItem(
DERTag tag,
DERSize length);
/* encode item */
DERReturn DEREncodeItem(
DERTag tag,
DERSize length,
const DERByte *src,
DERByte *derOut, /* encoded item goes here */
DERSize *inOutLen); /* IN/OUT */
/*
* Per-item encode options.
*/
/* explicit default, no options */
#define DER_ENC_NO_OPTS 0x0000
/* signed integer check: if incoming m.s. bit is 1, prepend a zero */
#define DER_ENC_SIGNED_INT 0x0100
/* DERItem contains fully encoded item - copy, don't encode */
#define DER_ENC_WRITE_DER 0x0200
/*
* High-level sequence or set encode support.
*
* The outgoing sequence is expressed as an array of DERItemSpecs, each
* of which corresponds to one item in the encoded sequence.
*
* Normally the tag of the encoded item comes from the associated
* DERItemSpec, and the content comes from the DERItem whose address is
* the src arg plus the offset value in the associated DERItemSpec.
*
* If the DER_ENC_WRITE_DER option is true for a given DERItemSpec then
* no per-item encoding is done; the DER - with tag, length, and content -
* is taken en masse from the associated DERItem.
*/
DERReturn DEREncodeSequence(
DERTag topTag, /* ASN1_CONSTR_SEQUENCE, ASN1_CONSTR_SET */
const void *src, /* generally a ptr to a struct full of
* DERItems */
DERShort numItems, /* size of itemSpecs[] */
const DERItemSpec *itemSpecs,
DERByte *derOut, /* encoded data written here */
DERSize *inOutLen); /* IN/OUT */
/* precalculate the length of an encoded sequence. */
DERSize DERLengthOfEncodedSequence(
DERTag topTag, /* ASN1_CONSTR_SEQUENCE, ASN1_CONSTR_SET */
const void *src, /* generally a ptr to a struct full of
* DERItems */
DERShort numItems, /* size of itemSpecs[] */
const DERItemSpec *itemSpecs);
__END_DECLS
#endif /* _DER_DECODE_H_ */
+167
View File
@@ -0,0 +1,167 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* DER_Cert.c - support for decoding RSA keys
*
* Created Nov. 8 2005 by Doug Mitchell.
*/
#include <libDER/DER_Decode.h>
#include <libDER/DER_Encode.h>
#include <libDER/DER_Keys.h>
#include <libDER/asn1Types.h>
#include <libDER/libDER_config.h>
#ifndef DER_DECODE_ENABLE
#error Please define DER_DECODE_ENABLE.
#endif
#if DER_DECODE_ENABLE
/*
* DERItemSpecs for decoding RSA keys.
*/
/* Algorithm Identifier */
const DERItemSpec DERAlgorithmIdItemSpecs[] =
{
{ DER_OFFSET(DERAlgorithmId, oid),
ASN1_OBJECT_ID,
DER_DEC_NO_OPTS },
{ DER_OFFSET(DERAlgorithmId, params),
0, /* no tag - any */
DER_DEC_ASN_ANY | DER_DEC_OPTIONAL | DER_DEC_SAVE_DER }
};
const DERSize DERNumAlgorithmIdItemSpecs =
sizeof(DERAlgorithmIdItemSpecs) / sizeof(DERItemSpec);
/* X509 SubjectPublicKeyInfo */
const DERItemSpec DERSubjPubKeyInfoItemSpecs[] =
{
{ DER_OFFSET(DERSubjPubKeyInfo, algId),
ASN1_CONSTR_SEQUENCE,
DER_DEC_NO_OPTS },
{ DER_OFFSET(DERSubjPubKeyInfo, pubKey),
ASN1_BIT_STRING,
DER_DEC_NO_OPTS },
};
const DERSize DERNumSubjPubKeyInfoItemSpecs =
sizeof(DERSubjPubKeyInfoItemSpecs) / sizeof(DERItemSpec);
/*
* RSA private key in CRT format
*/
const DERItemSpec DERRSAPrivKeyCRTItemSpecs[] =
{
/* version, n, e, d - skip */
{ 0,
ASN1_INTEGER,
DER_DEC_SKIP },
{ 0,
ASN1_INTEGER,
DER_DEC_SKIP },
{ 0,
ASN1_INTEGER,
DER_DEC_SKIP },
{ 0,
ASN1_INTEGER,
DER_DEC_SKIP },
{ DER_OFFSET(DERRSAPrivKeyCRT, p),
ASN1_INTEGER,
DER_DEC_NO_OPTS },
{ DER_OFFSET(DERRSAPrivKeyCRT, q),
ASN1_INTEGER,
DER_DEC_NO_OPTS },
{ DER_OFFSET(DERRSAPrivKeyCRT, dp),
ASN1_INTEGER,
DER_DEC_NO_OPTS },
{ DER_OFFSET(DERRSAPrivKeyCRT, dq),
ASN1_INTEGER,
DER_DEC_NO_OPTS },
{ DER_OFFSET(DERRSAPrivKeyCRT, qInv),
ASN1_INTEGER,
DER_DEC_NO_OPTS },
/* ignore the (optional) rest */
};
const DERSize DERNumRSAPrivKeyCRTItemSpecs =
sizeof(DERRSAPrivKeyCRTItemSpecs) / sizeof(DERItemSpec);
#endif /* DER_DECODE_ENABLE */
#if DER_DECODE_ENABLE || DER_ENCODE_ENABLE
/* RSA public key in PKCS1 format - encode and decode */
const DERItemSpec DERRSAPubKeyPKCS1ItemSpecs[] =
{
{ DER_OFFSET(DERRSAPubKeyPKCS1, modulus),
ASN1_INTEGER,
DER_DEC_NO_OPTS | DER_ENC_SIGNED_INT },
{ DER_OFFSET(DERRSAPubKeyPKCS1, pubExponent),
ASN1_INTEGER,
DER_DEC_NO_OPTS | DER_ENC_SIGNED_INT },
};
const DERSize DERNumRSAPubKeyPKCS1ItemSpecs =
sizeof(DERRSAPubKeyPKCS1ItemSpecs) / sizeof(DERItemSpec);
/* RSA public key in Apple custome format with reciprocal - encode and decode */
const DERItemSpec DERRSAPubKeyAppleItemSpecs[] =
{
{ DER_OFFSET(DERRSAPubKeyApple, modulus),
ASN1_INTEGER,
DER_DEC_NO_OPTS | DER_ENC_SIGNED_INT },
{ DER_OFFSET(DERRSAPubKeyApple, reciprocal),
ASN1_INTEGER,
DER_DEC_NO_OPTS | DER_ENC_SIGNED_INT },
{ DER_OFFSET(DERRSAPubKeyApple, pubExponent),
ASN1_INTEGER,
DER_DEC_NO_OPTS | DER_ENC_SIGNED_INT },
};
const DERSize DERNumRSAPubKeyAppleItemSpecs =
sizeof(DERRSAPubKeyAppleItemSpecs) / sizeof(DERItemSpec);
#endif /* DER_DECODE_ENABLE || DER_ENCODE_ENABLE */
#ifndef DER_ENCODE_ENABLE
#error Please define DER_ENCODE_ENABLE.
#endif
#if DER_ENCODE_ENABLE
/* RSA Key Pair, encode only */
const DERItemSpec DERRSAKeyPairItemSpecs[] =
{
{ DER_OFFSET(DERRSAKeyPair, version),
ASN1_INTEGER,
DER_ENC_SIGNED_INT },
{ DER_OFFSET(DERRSAKeyPair, n),
ASN1_INTEGER,
DER_ENC_SIGNED_INT },
{ DER_OFFSET(DERRSAKeyPair, e),
ASN1_INTEGER,
DER_ENC_SIGNED_INT },
{ DER_OFFSET(DERRSAKeyPair, d),
ASN1_INTEGER,
DER_ENC_SIGNED_INT },
{ DER_OFFSET(DERRSAKeyPair, p),
ASN1_INTEGER,
DER_ENC_SIGNED_INT },
{ DER_OFFSET(DERRSAKeyPair, q),
ASN1_INTEGER,
DER_ENC_SIGNED_INT },
{ DER_OFFSET(DERRSAKeyPair, dp),
ASN1_INTEGER,
DER_ENC_SIGNED_INT },
{ DER_OFFSET(DERRSAKeyPair, dq),
ASN1_INTEGER,
DER_ENC_SIGNED_INT },
{ DER_OFFSET(DERRSAKeyPair, qInv),
ASN1_INTEGER,
DER_ENC_SIGNED_INT },
};
const DERSize DERNumRSAKeyPairItemSpecs =
sizeof(DERRSAKeyPairItemSpecs) / sizeof(DERItemSpec);
#endif /* DER_ENCODE_ENABLE */
+99
View File
@@ -0,0 +1,99 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* DER_Keys.h - support for decoding RSA keys
*
* Created Nov. 8 2005 by dmitch
*/
#ifndef _DER_KEYS_H_
#define _DER_KEYS_H_
#include <libDER/libDER.h>
#include <libDER/DER_Decode.h>
__BEGIN_DECLS
/* Algorithm Identifier components */
typedef struct {
DERItem oid; /* OID */
DERItem params; /* ASN_ANY, optional, DER_DEC_SAVE_DER */
} DERAlgorithmId;
/* DERItemSpecs to decode into a DERAlgorithmId */
extern const DERItemSpec DERAlgorithmIdItemSpecs[];
extern const DERSize DERNumAlgorithmIdItemSpecs;
/* X509 SubjectPublicKeyInfo */
typedef struct {
DERItem algId; /* sequence, DERAlgorithmId */
DERItem pubKey; /* BIT STRING */
} DERSubjPubKeyInfo;
/* DERItemSpecs to decode into a DERSubjPubKeyInfo */
extern const DERItemSpec DERSubjPubKeyInfoItemSpecs[];
extern const DERSize DERNumSubjPubKeyInfoItemSpecs;
/*
* RSA public key in PKCS1 format; this is inside the BIT_STRING in
* DERSubjPubKeyInfo.pubKey.
*/
typedef struct {
DERItem modulus; /* n - INTEGER */
DERItem pubExponent; /* e - INTEGER */
} DERRSAPubKeyPKCS1;
/* DERItemSpecs to decode/encode into/from a DERRSAPubKeyPKCS1 */
extern const DERItemSpec DERRSAPubKeyPKCS1ItemSpecs[];
extern const DERSize DERNumRSAPubKeyPKCS1ItemSpecs;
/*
* RSA public key in custom (to this library) format, including
* the reciprocal. All fields are integers.
*/
typedef struct {
DERItem modulus; /* n */
DERItem reciprocal; /* reciprocal of modulus */
DERItem pubExponent; /* e */
} DERRSAPubKeyApple;
/* DERItemSpecs to decode/encode into/from a DERRSAPubKeyApple */
extern const DERItemSpec DERRSAPubKeyAppleItemSpecs[];
extern const DERSize DERNumRSAPubKeyAppleItemSpecs;
/*
* RSA Private key, PKCS1 format, CRT option.
* All fields are integers.
*/
typedef struct {
DERItem p; /* p * q = n */
DERItem q;
DERItem dp; /* d mod (p-1) */
DERItem dq; /* d mod (q-1) */
DERItem qInv;
} DERRSAPrivKeyCRT;
/* DERItemSpecs to decode into a DERRSAPrivKeyCRT */
extern const DERItemSpec DERRSAPrivKeyCRTItemSpecs[];
extern const DERSize DERNumRSAPrivKeyCRTItemSpecs;
/* Fully formed RSA key pair, for generating a PKCS1 private key */
typedef struct {
DERItem version;
DERItem n; /* modulus */
DERItem e; /* public exponent */
DERItem d; /* private exponent */
DERItem p; /* n = p*q */
DERItem q;
DERItem dp; /* d mod (p-1) */
DERItem dq; /* d mod (q-1) */
DERItem qInv; /* q^(-1) mod p */
} DERRSAKeyPair;
/* DERItemSpecs to encode a DERRSAKeyPair */
extern const DERItemSpec DERRSAKeyPairItemSpecs[];
extern const DERSize DERNumRSAKeyPairItemSpecs;
__END_DECLS
#endif /* _DER_KEYS_H_ */
+89
View File
@@ -0,0 +1,89 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* asn1Types.h - ASN.1/DER #defines - strictly hard coded per the real world
*
* Created Nov. 4 2005 by dmitch
*/
#ifndef _ASN1_TYPES_H_
#define _ASN1_TYPES_H_
#include <sys/cdefs.h>
__BEGIN_DECLS
/* copied from libsecurity_asn1 project */
#define ASN1_BOOLEAN 0x01
#define ASN1_INTEGER 0x02
#define ASN1_BIT_STRING 0x03
#define ASN1_OCTET_STRING 0x04
#define ASN1_NULL 0x05
#define ASN1_OBJECT_ID 0x06
#define ASN1_OBJECT_DESCRIPTOR 0x07
/* External type and instance-of type 0x08 */
#define ASN1_REAL 0x09
#define ASN1_ENUMERATED 0x0a
#define ASN1_EMBEDDED_PDV 0x0b
#define ASN1_UTF8_STRING 0x0c
/* 0x0d */
/* 0x0e */
/* 0x0f */
#define ASN1_SEQUENCE 0x10
#define ASN1_SET 0x11
#define ASN1_NUMERIC_STRING 0x12
#define ASN1_PRINTABLE_STRING 0x13
#define ASN1_T61_STRING 0x14
#define ASN1_VIDEOTEX_STRING 0x15
#define ASN1_IA5_STRING 0x16
#define ASN1_UTC_TIME 0x17
#define ASN1_GENERALIZED_TIME 0x18
#define ASN1_GRAPHIC_STRING 0x19
#define ASN1_VISIBLE_STRING 0x1a
#define ASN1_GENERAL_STRING 0x1b
#define ASN1_UNIVERSAL_STRING 0x1c
/* 0x1d */
#define ASN1_BMP_STRING 0x1e
#define ASN1_HIGH_TAG_NUMBER 0x1f
#define ASN1_TELETEX_STRING ASN1_T61_STRING
#ifdef DER_MULTIBYTE_TAGS
#define ASN1_TAG_MASK ((DERTag)~0)
#define ASN1_TAGNUM_MASK ((DERTag)~((DERTag)7 << (sizeof(DERTag) * 8 - 3)))
#define ASN1_METHOD_MASK ((DERTag)1 << (sizeof(DERTag) * 8 - 3))
#define ASN1_PRIMITIVE ((DERTag)0 << (sizeof(DERTag) * 8 - 3))
#define ASN1_CONSTRUCTED ((DERTag)1 << (sizeof(DERTag) * 8 - 3))
#define ASN1_CLASS_MASK ((DERTag)3 << (sizeof(DERTag) * 8 - 2))
#define ASN1_UNIVERSAL ((DERTag)0 << (sizeof(DERTag) * 8 - 2))
#define ASN1_APPLICATION ((DERTag)1 << (sizeof(DERTag) * 8 - 2))
#define ASN1_CONTEXT_SPECIFIC ((DERTag)2 << (sizeof(DERTag) * 8 - 2))
#define ASN1_PRIVATE ((DERTag)3 << (sizeof(DERTag) * 8 - 2))
#else /* DER_MULTIBYTE_TAGS */
#define ASN1_TAG_MASK 0xff
#define ASN1_TAGNUM_MASK 0x1f
#define ASN1_METHOD_MASK 0x20
#define ASN1_PRIMITIVE 0x00
#define ASN1_CONSTRUCTED 0x20
#define ASN1_CLASS_MASK 0xc0
#define ASN1_UNIVERSAL 0x00
#define ASN1_APPLICATION 0x40
#define ASN1_CONTEXT_SPECIFIC 0x80
#define ASN1_PRIVATE 0xc0
#endif /* !DER_MULTIBYTE_TAGS */
/* sequence and set appear as the following */
#define ASN1_CONSTR_SEQUENCE (ASN1_CONSTRUCTED | ASN1_SEQUENCE)
#define ASN1_CONSTR_SET (ASN1_CONSTRUCTED | ASN1_SET)
__END_DECLS
#endif /* _ASN1_TYPES_H_ */
+62
View File
@@ -0,0 +1,62 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* libDER.h - main header for libDER, a ROM-capable DER decoding library.
*
* Created Nov. 4 2005 by dmitch
*/
#ifndef _LIB_DER_H_
#define _LIB_DER_H_
#include <libDER/libDER_config.h>
__BEGIN_DECLS
/*
* Error returns generated by this library.
*/
typedef enum {
DR_Success = 0,
DR_EndOfSequence, /* end of sequence or set */
DR_UnexpectedTag, /* unexpected tag found while decoding */
DR_DecodeError, /* misc. decoding error (badly formatted DER) */
DR_Unimplemented, /* function not implemented in this configuration */
DR_IncompleteSeq, /* incomplete sequence */
DR_ParamErr, /* incoming parameter error */
DR_BufOverflow /* buffer overflow */
/* etc. */
} DERReturn;
/*
* Primary representation of a block of memory.
*/
typedef struct {
DERByte *data;
DERSize length;
} DERItem;
/*
* The structure of a sequence during decode or encode is expressed as
* an array of DERItemSpecs. While decoding or encoding a sequence,
* each item in the sequence corresponds to one DERItemSpec.
*/
typedef struct {
DERSize offset; /* offset of destination DERItem */
DERTag tag; /* DER tag */
DERShort options; /* DER_DEC_xxx or DER_ENC_xxx */
} DERItemSpec;
/*
* Macro to obtain offset of a DERDecodedInfo within a struct.
* FIXME this is going to need reworking to avoid compiler warnings
* on 64-bit compiles. It'll work OK as long as an offset can't be larger
* than a DERSize, but the cast from a pointer to a DERSize may
* provoke compiler warnings.
*/
#define DER_OFFSET(type, field) ((DERSize)(&((type *)0)->field))
__END_DECLS
#endif /* _LIB_DER_H_ */
+89
View File
@@ -0,0 +1,89 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* libDER_config.h - platform dependent #defines and typedefs for libDER
*
* Created Nov. 4 2005 by dmitch
*/
#ifndef _LIB_DER_CONFIG_H_
#define _LIB_DER_CONFIG_H_
#include <stdint.h>
#include <string.h>
#include <sys/cdefs.h>
__BEGIN_DECLS
/*
* Basic data types: unsigned 8-bit integer, unsigned 32-bit integer
*/
typedef uint8_t DERByte;
typedef uint16_t DERShort;
typedef uint32_t DERSize;
/*
* Use these #defines of you have memset, memmove, and memcmp; else
* write your own equivalents.
*/
#define DERMemset(ptr, c, len) memset(ptr, c, len)
#define DERMemmove(dst, src, len) memmove(dst, src, len)
#define DERMemcmp(b1, b2, len) memcmp(b1, b2, len)
/***
*** Compile time options to trim size of the library.
***/
/* enable general DER encode */
#define DER_ENCODE_ENABLE 1
/* enable general DER decode */
#define DER_DECODE_ENABLE 1
#ifndef DER_MULTIBYTE_TAGS
/* enable multibyte tag support. */
#define DER_MULTIBYTE_TAGS 1
#endif
#ifndef DER_TAG_SIZE
/* Iff DER_MULTIBYTE_TAGS is 1 this is the sizeof(DERTag) in bytes. Note that
tags are still encoded and decoded from a minimally encoded DER
represantation. This value determines how big each DERItemSpecs is, we
choose 2 since that makes DERItemSpecs 8 bytes wide. */
#define DER_TAG_SIZE 8
#endif
/* ---------------------- Do not edit below this line ---------------------- */
/*
* Logical representation of a tag (the encoded representation is always in
* the minimal number of bytes). The top 3 bits encode class and method
* The remaining bits encode the tag value. To obtain smaller DERItemSpecs
* sizes, choose the smallest type that fits your needs. Most standard ASN.1
* usage only needs single byte tags, but ocasionally custom applications
* require a larger tag namespace.
*/
#if DER_MULTIBYTE_TAGS
#if DER_TAG_SIZE == 1
typedef uint8_t DERTag;
#elif DER_TAG_SIZE == 2
typedef uint16_t DERTag;
#elif DER_TAG_SIZE == 4
typedef uint32_t DERTag;
#elif DER_TAG_SIZE == 8
typedef uint64_t DERTag;
#else
#error DER_TAG_SIZE invalid
#endif
#else /* DER_MULTIBYTE_TAGS */
typedef DERByte DERTag;
#endif /* !DER_MULTIBYTE_TAGS */
__END_DECLS
#endif /* _LIB_DER_CONFIG_H_ */
+516
View File
@@ -0,0 +1,516 @@
/* Copyright (c) 2005-2013, 2015 Apple Inc. All Rights Reserved. */
/*
* oids.c - OID consts
*
* Created Nov. 11 2005 by dmitch
*/
#include <libDER/libDER.h>
#include <libDER/oids.h>
#define OID_ISO_CCITT_DIR_SERVICE 85
#define OID_DS OID_ISO_CCITT_DIR_SERVICE
#define OID_ATTR_TYPE OID_DS, 4
#define OID_EXTENSION OID_DS, 29
#define OID_ISO_STANDARD 40
#define OID_ISO_MEMBER 42
#define OID_US OID_ISO_MEMBER, 134, 72
#define OID_ISO_IDENTIFIED_ORG 43
#define OID_OSINET OID_ISO_IDENTIFIED_ORG, 4
#define OID_GOSIP OID_ISO_IDENTIFIED_ORG, 5
#define OID_DOD OID_ISO_IDENTIFIED_ORG, 6
#define OID_OIW OID_ISO_IDENTIFIED_ORG, 14
/* From the PKCS Standards */
#define OID_RSA OID_US, 134, 247, 13
#define OID_RSA_HASH OID_RSA, 2
#define OID_RSA_ENCRYPT OID_RSA, 3
#define OID_PKCS OID_RSA, 1
#define OID_PKCS_1 OID_PKCS, 1
#define OID_PKCS_2 OID_PKCS, 2
#define OID_PKCS_3 OID_PKCS, 3
#define OID_PKCS_4 OID_PKCS, 4
#define OID_PKCS_5 OID_PKCS, 5
#define OID_PKCS_6 OID_PKCS, 6
#define OID_PKCS_7 OID_PKCS, 7
#define OID_PKCS_8 OID_PKCS, 8
#define OID_PKCS_9 OID_PKCS, 9
#define OID_PKCS_10 OID_PKCS, 10
#define OID_PKCS_11 OID_PKCS, 11
#define OID_PKCS_12 OID_PKCS, 12
/* ANSI X9.62 */
#define OID_ANSI_X9_62 OID_US, 206, 61
#define OID_PUBLIC_KEY_TYPE OID_ANSI_X9_62, 2
#define OID_EC_SIG_TYPE OID_ANSI_X9_62, 4
#define OID_ECDSA_WITH_SHA2 OID_EC_SIG_TYPE, 3
/* ANSI X9.42 */
#define OID_ANSI_X9_42 OID_US, 206, 62, 2
#define OID_ANSI_X9_42_SCHEME OID_ANSI_X9_42, 3
#define OID_ANSI_X9_42_NAMED_SCHEME OID_ANSI_X9_42, 4
/* DOD IANA Security releated objects. */
#define OID_IANA OID_DOD, 1, 5
/* Kerberos PKINIT */
#define OID_KERBv5 OID_IANA, 2
#define OID_KERBv5_PKINIT OID_KERBv5, 3
/* DOD IANA Mechanisms. */
#define OID_MECHANISMS OID_IANA, 5
/* PKIX */
#define OID_PKIX OID_MECHANISMS, 7
#define OID_PE OID_PKIX, 1
#define OID_QT OID_PKIX, 2
#define OID_KP OID_PKIX, 3
#define OID_OTHER_NAME OID_PKIX, 8
#define OID_PDA OID_PKIX, 9
#define OID_QCS OID_PKIX, 11
#define OID_AD OID_PKIX, 48
#define OID_AD_OCSP OID_AD, 1
#define OID_AD_CAISSUERS OID_AD, 2
/* ISAKMP */
#define OID_ISAKMP OID_MECHANISMS, 8
/* ETSI */
#define OID_ETSI 0x04, 0x00
#define OID_ETSI_QCS 0x04, 0x00, 0x8E, 0x46, 0x01
#define OID_OIW_SECSIG OID_OIW, 3
#define OID_OIW_ALGORITHM OID_OIW_SECSIG, 2
/* NIST defined digest algorithm arc (2, 16, 840, 1, 101, 3, 4, 2) */
#define OID_NIST_HASHALG 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02
/*
* Apple-specific OID bases
*/
/*
* apple OBJECT IDENTIFIER ::=
* { iso(1) member-body(2) US(840) 113635 }
*
* BER = 06 06 2A 86 48 86 F7 63
*/
#define APPLE_OID OID_US, 0x86, 0xf7, 0x63
/* appleDataSecurity OBJECT IDENTIFIER ::=
* { apple 100 }
* { 1 2 840 113635 100 }
*
* BER = 06 07 2A 86 48 86 F7 63 64
*/
#define APPLE_ADS_OID APPLE_OID, 0x64
/*
* appleTrustPolicy OBJECT IDENTIFIER ::=
* { appleDataSecurity 1 }
* { 1 2 840 113635 100 1 }
*
* BER = 06 08 2A 86 48 86 F7 63 64 01
*/
#define APPLE_TP_OID APPLE_ADS_OID, 1
/*
* appleSecurityAlgorithm OBJECT IDENTIFIER ::=
* { appleDataSecurity 2 }
* { 1 2 840 113635 100 2 }
*
* BER = 06 08 2A 86 48 86 F7 63 64 02
*/
#define APPLE_ALG_OID APPLE_ADS_OID, 2
/*
* appleDotMacCertificate OBJECT IDENTIFIER ::=
* { appleDataSecurity 3 }
* { 1 2 840 113635 100 3 }
*/
#define APPLE_DOTMAC_CERT_OID APPLE_ADS_OID, 3
/*
* Basis of Policy OIDs for .mac TP requests
*
* dotMacCertificateRequest OBJECT IDENTIFIER ::=
* { appleDotMacCertificate 1 }
* { 1 2 840 113635 100 3 1 }
*/
#define APPLE_DOTMAC_CERT_REQ_OID APPLE_DOTMAC_CERT_OID, 1
/*
* Basis of .mac Certificate Extensions
*
* dotMacCertificateExtension OBJECT IDENTIFIER ::=
* { appleDotMacCertificate 2 }
* { 1 2 840 113635 100 3 2 }
*/
#define APPLE_DOTMAC_CERT_EXTEN_OID APPLE_DOTMAC_CERT_OID, 2
/*
* Basis of .mac Certificate request OID/value identitifiers
*
* dotMacCertificateRequestValues OBJECT IDENTIFIER ::=
* { appleDotMacCertificate 3 }
* { 1 2 840 113635 100 3 3 }
*/
#define APPLE_DOTMAC_CERT_REQ_VALUE_OID APPLE_DOTMAC_CERT_OID, 3
/*
* Basis of Apple-specific extended key usages
*
* appleExtendedKeyUsage OBJECT IDENTIFIER ::=
* { appleDataSecurity 4 }
* { 1 2 840 113635 100 4 }
*/
#define APPLE_EKU_OID APPLE_ADS_OID, 4
/*
* Basis of Apple Code Signing extended key usages
* appleCodeSigning OBJECT IDENTIFIER ::=
* { appleExtendedKeyUsage 1 }
* { 1 2 840 113635 100 4 1}
*/
#define APPLE_EKU_CODE_SIGNING APPLE_EKU_OID, 1
#define APPLE_EKU_APPLE_ID APPLE_EKU_OID, 7
#define APPLE_EKU_SHOEBOX APPLE_EKU_OID, 14
/*
* Basis of Apple-specific Certific Policy IDs.
* appleCertificatePolicies OBJECT IDENTIFIER ::=
* { appleDataSecurity 5 }
* { 1 2 840 113635 100 5 }
*/
#define APPLE_CERT_POLICIES APPLE_ADS_OID, 5
/*
* Basis of Apple-specific Signing extensions
* { appleDataSecurity 6 }
*/
#define APPLE_CERT_EXT APPLE_ADS_OID, 6
/* Apple Intermediate Marker OIDs */
#define APPLE_CERT_EXT_INTERMEDIATE_MARKER APPLE_CERT_EXT, 2
/* Apple Apple ID Intermediate Marker */
#define APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID APPLE_CERT_EXT_INTERMEDIATE_MARKER, 3
/*
* Apple Apple ID Intermediate Marker (New subCA, no longer shared with push notification server cert issuer
*
* appleCertificateExtensionAppleIDIntermediate ::=
* { appleCertificateExtensionIntermediateMarker 7 }
* { 1 2 840 113635 100 6 2 7 }
*/
#define APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID_2 APPLE_CERT_EXT_INTERMEDIATE_MARKER, 7
#define APPLE_CERT_EXT_APPLE_PUSH_MARKER APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID, 2
#define APPLE_CERT_EXTENSION_CODESIGNING APPLE_CERT_EXT, 1
/* Secure Boot Embedded Image3 value,
co-opted by desktop for "Apple Released Code Signature", without value */
#define APPLE_SBOOT_CERT_EXTEN_SBOOT_SPEC_OID APPLE_CERT_EXTENSION_CODESIGNING, 1
#define APPLE_SBOOT_CERT_EXTEN_SBOOT_TICKET_SPEC_OID APPLE_CERT_EXTENSION_CODESIGNING, 11
#define APPLE_SBOOT_CERT_EXTEN_IMG4_MANIFEST_SPEC_OID APPLE_CERT_EXTENSION_CODESIGNING, 15
/* iPhone Provisioning Profile Signing leaf - on the intermediate marker arc? */
#define APPLE_PROVISIONING_PROFILE_OID APPLE_CERT_EXT_INTERMEDIATE_MARKER, 1
/* iPhone Application Signing leaf */
#define APPLE_APP_SIGINING_OID APPLE_CERT_EXTENSION_CODESIGNING, 3
/* Shoebox card signing leaf */
#define APPLE_INSTALLER_PACKAGE_SIGNING_EXTERNAL_OID APPLE_CERT_EXTENSION_CODESIGNING, 16
/*
* Netscape OIDs.
*/
#define NETSCAPE_BASE_OID 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42
/*
* Netscape cert extension.
*
* netscape-cert-extension OBJECT IDENTIFIER ::=
* { 2 16 840 1 113730 1 }
*
* BER = 06 08 60 86 48 01 86 F8 42 01
*/
#define NETSCAPE_CERT_EXTEN NETSCAPE_BASE_OID, 0x01
#define NETSCAPE_CERT_POLICY NETSCAPE_BASE_OID, 0x04
/* Entrust OIDs. */
#define ENTRUST_BASE_OID OID_US, 0x86, 0xf6, 0x7d
/*
* Entrust cert extension.
*
* entrust-cert-extension OBJECT IDENTIFIER ::=
* { 1 2 840 113533 7 65 }
*
* BER = 06 08 2A 86 48 86 F6 7D 07 41
*/
#define ENTRUST_CERT_EXTEN ENTRUST_BASE_OID, 0x07, 0x41
/* Microsfot OIDs. */
#define MICROSOFT_BASE_OID OID_DOD, 0x01, 0x04, 0x01, 0x82, 0x37
#define MICROSOFT_ENROLLMENT_OID MICROSOFT_BASE_OID, 0x14
/* Algorithm OIDs. */
static const DERByte
_oidRsa[] = { OID_PKCS_1, 1 },
_oidMd2Rsa[] = { OID_PKCS_1, 2 },
_oidMd5Rsa[] = { OID_PKCS_1, 4 },
_oidSha1Rsa[] = { OID_PKCS_1, 5 },
_oidSha256Rsa[] = { OID_PKCS_1, 11 }, /* rfc5754 */
_oidSha384Rsa[] = { OID_PKCS_1, 12 }, /* rfc5754 */
_oidSha512Rsa[] = { OID_PKCS_1, 13 }, /* rfc5754 */
_oidSha224Rsa[] = { OID_PKCS_1, 14 }, /* rfc5754 */
_oidEcPubKey[] = { OID_PUBLIC_KEY_TYPE, 1 },
_oidSha1Ecdsa[] = { OID_EC_SIG_TYPE, 1 }, /* rfc3279 */
_oidSha224Ecdsa[] = { OID_ECDSA_WITH_SHA2, 1 }, /* rfc5758 */
_oidSha256Ecdsa[] = { OID_ECDSA_WITH_SHA2, 2 }, /* rfc5758 */
_oidSha384Ecdsa[] = { OID_ECDSA_WITH_SHA2, 3 }, /* rfc5758 */
_oidSha512Ecdsa[] = { OID_ECDSA_WITH_SHA2, 4 }, /* rfc5758 */
_oidMd2[] = { OID_RSA_HASH, 2 },
_oidMd4[] = { OID_RSA_HASH, 4 },
_oidMd5[] = { OID_RSA_HASH, 5 },
_oidSha1[] = { OID_OIW_ALGORITHM, 26 },
_oidSha256[] = { OID_NIST_HASHALG, 1 },
_oidSha384[] = { OID_NIST_HASHALG, 2 },
_oidSha512[] = { OID_NIST_HASHALG, 3 },
_oidSha224[] = { OID_NIST_HASHALG, 4 };
const DERItem
oidRsa = { (DERByte *)_oidRsa,
sizeof(_oidRsa) },
oidMd2Rsa = { (DERByte *)_oidMd2Rsa,
sizeof(_oidMd2Rsa) },
oidMd5Rsa = { (DERByte *)_oidMd5Rsa,
sizeof(_oidMd5Rsa) },
oidSha1Rsa = { (DERByte *)_oidSha1Rsa,
sizeof(_oidSha1Rsa) },
oidSha224Rsa = { (DERByte *)_oidSha224Rsa,
sizeof(_oidSha224Rsa) },
oidSha256Rsa = { (DERByte *)_oidSha256Rsa,
sizeof(_oidSha256Rsa) },
oidSha384Rsa = { (DERByte *)_oidSha384Rsa,
sizeof(_oidSha384Rsa) },
oidSha512Rsa = { (DERByte *)_oidSha512Rsa,
sizeof(_oidSha512Rsa) },
oidEcPubKey = { (DERByte *)_oidEcPubKey,
sizeof(_oidEcPubKey) },
oidSha1Ecdsa = { (DERByte *)_oidSha1Ecdsa,
sizeof(_oidSha1Ecdsa) },
oidSha224Ecdsa = { (DERByte *)_oidSha224Ecdsa,
sizeof(_oidSha224Ecdsa) },
oidSha256Ecdsa = { (DERByte *)_oidSha256Ecdsa,
sizeof(_oidSha256Ecdsa) },
oidSha384Ecdsa = { (DERByte *)_oidSha384Ecdsa,
sizeof(_oidSha384Ecdsa) },
oidSha512Ecdsa = { (DERByte *)_oidSha512Ecdsa,
sizeof(_oidSha512Ecdsa) },
oidMd2 = { (DERByte *)_oidMd2,
sizeof(_oidMd2) },
oidMd4 = { (DERByte *)_oidMd4,
sizeof(_oidMd4) },
oidMd5 = { (DERByte *)_oidMd5,
sizeof(_oidMd5) },
oidSha1 = { (DERByte *)_oidSha1,
sizeof(_oidSha1) },
oidSha256 = { (DERByte *)_oidSha256,
sizeof(_oidSha256) },
oidSha384 = { (DERByte *)_oidSha384,
sizeof(_oidSha384) },
oidSha512 = { (DERByte *)_oidSha512,
sizeof(_oidSha512) },
oidSha224 = { (DERByte *)_oidSha224,
sizeof(_oidSha224) };
/* Extension OIDs. */
static const DERByte
_oidSubjectKeyIdentifier[] = { OID_EXTENSION, 14 },
_oidKeyUsage[] = { OID_EXTENSION, 15 },
_oidPrivateKeyUsagePeriod[] = { OID_EXTENSION, 16 },
_oidSubjectAltName[] = { OID_EXTENSION, 17 },
_oidIssuerAltName[] = { OID_EXTENSION, 18 },
_oidBasicConstraints[] = { OID_EXTENSION, 19 },
_oidCrlDistributionPoints[] = { OID_EXTENSION, 31 },
_oidCertificatePolicies[] = { OID_EXTENSION, 32 },
_oidAnyPolicy[] = { OID_EXTENSION, 32, 0 },
_oidPolicyMappings[] = { OID_EXTENSION, 33 },
_oidAuthorityKeyIdentifier[] = { OID_EXTENSION, 35 },
_oidPolicyConstraints[] = { OID_EXTENSION, 36 },
_oidExtendedKeyUsage[] = { OID_EXTENSION, 37 },
_oidAnyExtendedKeyUsage[] = { OID_EXTENSION, 37, 0 },
_oidInhibitAnyPolicy[] = { OID_EXTENSION, 54 },
_oidAuthorityInfoAccess[] = { OID_PE, 1 },
_oidSubjectInfoAccess[] = { OID_PE, 11 },
_oidAdOCSP[] = { OID_AD_OCSP },
_oidAdCAIssuer[] = { OID_AD_CAISSUERS },
_oidNetscapeCertType[] = { NETSCAPE_CERT_EXTEN, 1 },
_oidEntrustVersInfo[] = { ENTRUST_CERT_EXTEN, 0 },
_oidMSNTPrincipalName[] = { MICROSOFT_ENROLLMENT_OID, 2, 3 },
/* Policy Qualifier IDs for Internet policy qualifiers. */
_oidQtCps[] = { OID_QT, 1 },
_oidQtUNotice[] = { OID_QT, 2 },
/* X.501 Name IDs. */
_oidCommonName[] = { OID_ATTR_TYPE, 3 },
_oidCountryName[] = { OID_ATTR_TYPE, 6 },
_oidLocalityName[] = { OID_ATTR_TYPE, 7 },
_oidStateOrProvinceName[] = { OID_ATTR_TYPE, 8 },
_oidOrganizationName[] = { OID_ATTR_TYPE, 10 },
_oidOrganizationalUnitName[] = { OID_ATTR_TYPE, 11 },
_oidDescription[] = { OID_ATTR_TYPE, 13 },
_oidEmailAddress[] = { OID_PKCS_9, 1 },
_oidFriendlyName[] = { OID_PKCS_9, 20 },
_oidLocalKeyId[] = { OID_PKCS_9, 21 },
_oidExtendedKeyUsageServerAuth[] = { OID_KP, 1 },
_oidExtendedKeyUsageClientAuth[] = { OID_KP, 2 },
_oidExtendedKeyUsageCodeSigning[] = { OID_KP, 3 },
_oidExtendedKeyUsageEmailProtection[] = { OID_KP, 4 },
_oidExtendedKeyUsageOCSPSigning[] = { OID_KP, 9 },
_oidExtendedKeyUsageIPSec[] = { OID_ISAKMP, 2, 2 },
_oidExtendedKeyUsageMicrosoftSGC[] = { MICROSOFT_BASE_OID, 10, 3, 3 },
_oidExtendedKeyUsageNetscapeSGC[] = { NETSCAPE_CERT_POLICY, 1 },
_oidAppleSecureBootCertSpec[] = { APPLE_SBOOT_CERT_EXTEN_SBOOT_SPEC_OID },
_oidAppleSecureBootTicketCertSpec[] = { APPLE_SBOOT_CERT_EXTEN_SBOOT_TICKET_SPEC_OID },
_oidAppleImg4ManifestCertSpec[] = {
APPLE_SBOOT_CERT_EXTEN_IMG4_MANIFEST_SPEC_OID },
_oidAppleProvisioningProfile[] = {APPLE_PROVISIONING_PROFILE_OID },
_oidAppleApplicationSigning[] = { APPLE_APP_SIGINING_OID },
_oidAppleInstallerPackagingSigningExternal[] = { APPLE_INSTALLER_PACKAGE_SIGNING_EXTERNAL_OID },
_oidAppleExtendedKeyUsageAppleID[] = { APPLE_EKU_APPLE_ID },
_oidAppleExtendedKeyUsageShoebox[] = { APPLE_EKU_SHOEBOX },
#if 0 // unused
_oidApplePushServiceClient[] = { APPLE_CERT_EXT_APPLE_PUSH_MARKER, 2 },
#endif
_oidAppleIntmMarkerAppleID[] = { APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID },
_oidAppleIntmMarkerAppleID2[] = {APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID_2 };
const DERItem
oidSubjectKeyIdentifier = { (DERByte *)_oidSubjectKeyIdentifier,
sizeof(_oidSubjectKeyIdentifier) },
oidKeyUsage = { (DERByte *)_oidKeyUsage,
sizeof(_oidKeyUsage) },
oidPrivateKeyUsagePeriod = { (DERByte *)_oidPrivateKeyUsagePeriod,
sizeof(_oidPrivateKeyUsagePeriod) },
oidSubjectAltName = { (DERByte *)_oidSubjectAltName,
sizeof(_oidSubjectAltName) },
oidIssuerAltName = { (DERByte *)_oidIssuerAltName,
sizeof(_oidIssuerAltName) },
oidBasicConstraints = { (DERByte *)_oidBasicConstraints,
sizeof(_oidBasicConstraints) },
oidCrlDistributionPoints = { (DERByte *)_oidCrlDistributionPoints,
sizeof(_oidCrlDistributionPoints) },
oidCertificatePolicies = { (DERByte *)_oidCertificatePolicies,
sizeof(_oidCertificatePolicies) },
oidAnyPolicy = { (DERByte *)_oidAnyPolicy,
sizeof(_oidAnyPolicy) },
oidPolicyMappings = { (DERByte *)_oidPolicyMappings,
sizeof(_oidPolicyMappings) },
oidAuthorityKeyIdentifier = { (DERByte *)_oidAuthorityKeyIdentifier,
sizeof(_oidAuthorityKeyIdentifier) },
oidPolicyConstraints = { (DERByte *)_oidPolicyConstraints,
sizeof(_oidPolicyConstraints) },
oidExtendedKeyUsage = { (DERByte *)_oidExtendedKeyUsage,
sizeof(_oidExtendedKeyUsage) },
oidAnyExtendedKeyUsage = { (DERByte *)_oidAnyExtendedKeyUsage,
sizeof(_oidAnyExtendedKeyUsage) },
oidInhibitAnyPolicy = { (DERByte *)_oidInhibitAnyPolicy,
sizeof(_oidInhibitAnyPolicy) },
oidAuthorityInfoAccess = { (DERByte *)_oidAuthorityInfoAccess,
sizeof(_oidAuthorityInfoAccess) },
oidSubjectInfoAccess = { (DERByte *)_oidSubjectInfoAccess,
sizeof(_oidSubjectInfoAccess) },
oidAdOCSP = { (DERByte *)_oidAdOCSP,
sizeof(_oidAdOCSP) },
oidAdCAIssuer = { (DERByte *)_oidAdCAIssuer,
sizeof(_oidAdCAIssuer) },
oidNetscapeCertType = { (DERByte *)_oidNetscapeCertType,
sizeof(_oidNetscapeCertType) },
oidEntrustVersInfo = { (DERByte *)_oidEntrustVersInfo,
sizeof(_oidEntrustVersInfo) },
oidMSNTPrincipalName = { (DERByte *)_oidMSNTPrincipalName,
sizeof(_oidMSNTPrincipalName) },
/* Policy Qualifier IDs for Internet policy qualifiers. */
oidQtCps = { (DERByte *)_oidQtCps,
sizeof(_oidQtCps) },
oidQtUNotice = { (DERByte *)_oidQtUNotice,
sizeof(_oidQtUNotice) },
/* X.501 Name IDs. */
oidCommonName = { (DERByte *)_oidCommonName,
sizeof(_oidCommonName) },
oidCountryName = { (DERByte *)_oidCountryName,
sizeof(_oidCountryName) },
oidLocalityName = { (DERByte *)_oidLocalityName,
sizeof(_oidLocalityName) },
oidStateOrProvinceName = { (DERByte *)_oidStateOrProvinceName,
sizeof(_oidStateOrProvinceName) },
oidOrganizationName = { (DERByte *)_oidOrganizationName,
sizeof(_oidOrganizationName) },
oidOrganizationalUnitName = { (DERByte *)_oidOrganizationalUnitName,
sizeof(_oidOrganizationalUnitName) },
oidDescription = { (DERByte *)_oidDescription,
sizeof(_oidDescription) },
oidEmailAddress = { (DERByte *)_oidEmailAddress,
sizeof(_oidEmailAddress) },
oidFriendlyName = { (DERByte *)_oidFriendlyName,
sizeof(_oidFriendlyName) },
oidLocalKeyId = { (DERByte *)_oidLocalKeyId,
sizeof(_oidLocalKeyId) },
oidExtendedKeyUsageServerAuth = { (DERByte *)_oidExtendedKeyUsageServerAuth,
sizeof(_oidExtendedKeyUsageServerAuth) },
oidExtendedKeyUsageClientAuth = { (DERByte *)_oidExtendedKeyUsageClientAuth,
sizeof(_oidExtendedKeyUsageClientAuth) },
oidExtendedKeyUsageCodeSigning = { (DERByte *)_oidExtendedKeyUsageCodeSigning,
sizeof(_oidExtendedKeyUsageCodeSigning) },
oidExtendedKeyUsageEmailProtection = { (DERByte *)_oidExtendedKeyUsageEmailProtection,
sizeof(_oidExtendedKeyUsageEmailProtection) },
oidExtendedKeyUsageOCSPSigning = { (DERByte *)_oidExtendedKeyUsageOCSPSigning,
sizeof(_oidExtendedKeyUsageOCSPSigning) },
oidExtendedKeyUsageIPSec = { (DERByte *)_oidExtendedKeyUsageIPSec,
sizeof(_oidExtendedKeyUsageIPSec) },
oidExtendedKeyUsageMicrosoftSGC = { (DERByte *)_oidExtendedKeyUsageMicrosoftSGC,
sizeof(_oidExtendedKeyUsageMicrosoftSGC) },
oidExtendedKeyUsageNetscapeSGC = { (DERByte *)_oidExtendedKeyUsageNetscapeSGC,
sizeof(_oidExtendedKeyUsageNetscapeSGC) },
oidAppleSecureBootCertSpec = { (DERByte *)_oidAppleSecureBootCertSpec,
sizeof(_oidAppleSecureBootCertSpec) },
oidAppleSecureBootTicketCertSpec = { (DERByte *)_oidAppleSecureBootTicketCertSpec,
sizeof(_oidAppleSecureBootTicketCertSpec) },
oidAppleImg4ManifestCertSpec = { (DERByte *)
_oidAppleImg4ManifestCertSpec,
sizeof(_oidAppleImg4ManifestCertSpec) },
oidAppleProvisioningProfile = { (DERByte *)_oidAppleProvisioningProfile,
sizeof(_oidAppleProvisioningProfile) },
oidAppleApplicationSigning = { (DERByte *)_oidAppleApplicationSigning,
sizeof(_oidAppleApplicationSigning) },
oidAppleInstallerPackagingSigningExternal = { (DERByte *)_oidAppleInstallerPackagingSigningExternal,
sizeof(_oidAppleInstallerPackagingSigningExternal) },
oidAppleExtendedKeyUsageAppleID = { (DERByte *)_oidAppleExtendedKeyUsageAppleID,
sizeof(_oidAppleExtendedKeyUsageAppleID) },
oidAppleExtendedKeyUsageShoebox = { (DERByte *)_oidAppleExtendedKeyUsageShoebox,
sizeof(_oidAppleExtendedKeyUsageShoebox) },
oidAppleIntmMarkerAppleID = { (DERByte *)_oidAppleIntmMarkerAppleID,
sizeof(_oidAppleIntmMarkerAppleID) },
oidAppleIntmMarkerAppleID2 = { (DERByte *)_oidAppleIntmMarkerAppleID2,
sizeof(_oidAppleIntmMarkerAppleID2) },
oidApplePushServiceClient = { (DERByte *)_oidAppleIntmMarkerAppleID2,
sizeof(_oidAppleIntmMarkerAppleID2) };
bool DEROidCompare(const DERItem *oid1, const DERItem *oid2) {
if ((oid1 == NULL) || (oid2 == NULL)) {
return false;
}
if (oid1->length != oid2->length) {
return false;
}
if (!DERMemcmp(oid1->data, oid2->data, oid1->length)) {
return true;
} else {
return false;
}
}
+108
View File
@@ -0,0 +1,108 @@
/* Copyright (c) 2005-2009, 2011-2012, 2015 Apple Inc. All Rights Reserved. */
/*
* oids.h - declaration of OID consts
*
* Created Nov. 11 2005 by dmitch
*/
#ifndef _LIB_DER_OIDS_H_
#define _LIB_DER_OIDS_H_
#include <libDER/libDER.h>
#include <stdbool.h>
__BEGIN_DECLS
/* Algorithm oids. */
extern const DERItem
oidRsa, /* PKCS1 RSA encryption, used to identify RSA keys */
oidMd2Rsa, /* PKCS1 md2withRSAEncryption signature alg */
oidMd5Rsa, /* PKCS1 md5withRSAEncryption signature alg */
oidSha1Rsa, /* PKCS1 sha1withRSAEncryption signature alg */
oidSha224Rsa, /* PKCS1 sha224WithRSAEncryption signature alg */
oidSha256Rsa, /* PKCS1 sha256WithRSAEncryption signature alg */
oidSha384Rsa, /* PKCS1 sha384WithRSAEncryption signature alg */
oidSha512Rsa, /* PKCS1 sha512WithRSAEncryption signature alg */
oidEcPubKey, /* ECDH or ECDSA public key in a certificate */
oidSha1Ecdsa, /* ECDSA with SHA1 signature alg */
oidSha224Ecdsa, /* ECDSA with SHA224 signature alg */
oidSha256Ecdsa, /* ECDSA with SHA256 signature alg */
oidSha384Ecdsa, /* ECDSA with SHA384 signature alg */
oidSha512Ecdsa, /* ECDSA with SHA512 signature alg */
oidMd2, /* OID_RSA_HASH 2 */
oidMd4, /* OID_RSA_HASH 4 */
oidMd5, /* OID_RSA_HASH 5 */
oidSha1, /* OID_OIW_ALGORITHM 26 */
oidSha256, /* OID_NIST_HASHALG 1 */
oidSha384, /* OID_NIST_HASHALG 2 */
oidSha512, /* OID_NIST_HASHALG 3 */
oidSha224; /* OID_NIST_HASHALG 4 */
/* Standard X.509 Cert and CRL extensions. */
extern const DERItem
oidSubjectKeyIdentifier,
oidKeyUsage,
oidPrivateKeyUsagePeriod,
oidSubjectAltName,
oidIssuerAltName,
oidBasicConstraints,
oidCrlDistributionPoints,
oidCertificatePolicies,
oidAnyPolicy,
oidPolicyMappings,
oidAuthorityKeyIdentifier,
oidPolicyConstraints,
oidExtendedKeyUsage,
oidAnyExtendedKeyUsage,
oidInhibitAnyPolicy,
oidAuthorityInfoAccess,
oidSubjectInfoAccess,
oidAdOCSP,
oidAdCAIssuer,
oidNetscapeCertType,
oidEntrustVersInfo,
oidMSNTPrincipalName,
/* Policy Qualifier IDs for Internet policy qualifiers. */
oidQtCps,
oidQtUNotice,
/* X.501 Name IDs. */
oidCommonName,
oidCountryName,
oidLocalityName,
oidStateOrProvinceName,
oidOrganizationName,
oidOrganizationalUnitName,
oidDescription,
oidEmailAddress,
oidFriendlyName,
oidLocalKeyId,
oidExtendedKeyUsageServerAuth,
oidExtendedKeyUsageClientAuth,
oidExtendedKeyUsageCodeSigning,
oidExtendedKeyUsageEmailProtection,
oidExtendedKeyUsageOCSPSigning,
oidExtendedKeyUsageIPSec,
oidExtendedKeyUsageMicrosoftSGC,
oidExtendedKeyUsageNetscapeSGC,
/* Secure Boot Spec oid */
oidAppleSecureBootCertSpec,
/* Ticket-Based Secure Boot Spec oid */
oidAppleSecureBootTicketCertSpec,
/* Image4 Manifest Signing Cert Spec */
oidAppleImg4ManifestCertSpec,
oidAppleProvisioningProfile,
oidAppleApplicationSigning,
oidAppleInstallerPackagingSigningExternal,
oidAppleExtendedKeyUsageAppleID,
oidAppleExtendedKeyUsageShoebox,
oidAppleIntmMarkerAppleID,
oidAppleIntmMarkerAppleID2,
oidApplePushServiceClient;
/* Compare two decoded OIDs. Returns true iff they are equivalent. */
bool DEROidCompare(const DERItem *oid1, const DERItem *oid2);
__END_DECLS
#endif /* _LIB_DER_UTILS_H_ */
+63
View File
@@ -0,0 +1,63 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* giantDebug.c - debugging support
*
* Created Aug. 5 2005 by Doug Mitchell.
*/
#include <libGiants/giantDebug.h>
#include <libGiants/giantTypes.h>
#if GIANTS_DEBUG
void GIRaise(const char *str)
{
printf("Fatal libGiants library error: %s\n", str);
exit(1);
}
#endif /* GIANTS_DEBUG */
#if GI_STACK_DEBUG
void *gInitSp;
void *giLowestSp;
void GI_SET_INIT_SP(void)
{
gInitSp = GI_GET_SP();
giLowestSp = NULL;
}
#ifdef __ppc__
void *GI_GET_SP(void)
{
void *currsp;
asm("mr %0,r1" : "=r"(currsp) : );
return currsp;
}
#else
#ifdef __i386__
void *GI_GET_SP(void)
{
register void *sp __asm__("esp");
return sp;
}
#else
#ifdef __arm__
void *GI_GET_SP(void)
{
register void *sp __asm__("r13");
return sp;
}
#else
#error Need a platform-dependent GI_GET_SP()
#endif
#endif
#endif
#endif /* GI_STACK_DEBUG */
+101
View File
@@ -0,0 +1,101 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* giantDebug.h - debugging support.
*
* Created Aug. 5 2005 by Doug Mitchell.
*/
#ifndef _GIANT_DEBUG_H_
#define _GIANT_DEBUG_H_
#include <libGiants/giantPlatform.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef GIANTS_DEBUG
/* Should be defined in giantPlatform.h */
#error Please defgine GIANTS_DEBUG.
#endif
#if GIANTS_DEBUG
#include <assert.h>
#include <debug.h>
#include <stdlib.h>
#include <stdio.h>
#define dbgLog(str) printf(str)
#define GIASSERT(s) assert(s)
#else /* GIANTS_DEBUG */
#define dbgLog(str)
#define GIASSERT(s)
#endif /* GIANTS_DEBUG */
#undef NULL
#define NULL ((void *)0)
#if GIANTS_DEBUG
void GIRaise(const char *str) __attribute((noreturn));
#else
#define GIRaise(s)
#endif
/* detect overflow og giant->n[] */
#define CHECK_GIANT_OFLOW(g) GIASSERT((g)->sign <= (g)->capacity)
/* stack analysis support */
#if GI_STACK_DEBUG
#include <stdio.h>
extern void *gInitSp;
extern void *giLowestSp;
extern void GI_SET_INIT_SP(void);
extern void *GI_GET_SP(void);
static inline void GI_CHECK_SP(const char *fcn)
{
void *currSp = GI_GET_SP();
if((giLowestSp == NULL) || (currSp < giLowestSp)) {
giLowestSp = currSp;
printf("%s: new min sp %p; stack used %d\n", fcn,
giLowestSp,
gInitSp ? (gInitSp - giLowestSp) : 0);
}
}
/* this does some fine-grain stack logging regardless of giLowestSp */
#if GI_STACK_LOG
static inline void GI_LOG_SP(const char *fcn)
{
void *currSp = GI_GET_SP();
printf("%s: sp %p; stack used %d\n",
fcn, currSp,
gInitSp ? (gInitSp - currSp) : 0);
}
#else
#define GI_LOG_SP(fcn)
#endif /* GI_STACK_LOG */
#else /* GI_STACK_DEBUG */
#define GI_SET_INIT_SP()
#define GI_GET_SP()
#define GI_CHECK_SP(fcn)
#define GI_LOG_SP(fcn)
#endif /* GI_STACK_DEBUG */
#ifdef __cplusplus
}
#endif
#endif /* _GIANT_DEBUG_H_ */
+191
View File
@@ -0,0 +1,191 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* giantExternal.c - convert between giant integer and external representation
*
* Created Aug. 5 2005 by Doug Mitchell.
*/
#include <libGiants/giantTypes.h>
#include <libGiants/giantExternal.h>
#include <libGiants/giantDebug.h>
#include <stdlib.h>
/*
* Precalculate actual size in bytes needed to serialize a given giant.
*/
gi_uint16 serializeGiantBytes(const giant g)
{
gi_size numDigits, numZeros, digitByte;
giantDigit digit;
gtrimSign(g);
numDigits = g->sign;
if(numDigits == 0) {
return 0;
}
/* Count the number of leading 0 bytes in the m.s. digit. */
numZeros = 0;
digit = g->n[numDigits - 1];
for(digitByte=0; digitByte<GIANT_BYTES_PER_DIGIT; digitByte++) {
/* one loop per byte in the digit */
gi_uint8 byte = (gi_uint8)digit;
digit >>= 8;
if (byte) {
numZeros = 0;
} else {
numZeros++;
}
}
return (numDigits * GIANT_BYTES_PER_DIGIT) - numZeros;
}
/*
* Serialize, deserialize giants's n[] to/from byte stream.
* First byte of byte stream is the m.s. byte of the resulting giant,
* regardless of the size of giantDigit.
*
* No assumption is made about the alignment of cp.
*
* The numBytes argument indicates the space available on input;
* on return it indicates the actual number of bytes written.
*/
GIReturn serializeGiant(
const giant g,
gi_uint8 *cp,
gi_uint16 *numBytes) /* IN/OUT */
{
gi_size digitDex, numDigits, digitByte, totalBytes, bytesLeft;
gi_uint8 *currCp;
giantDigit digit;
GI_CHECK_SP("serializeGiant");
if((g == NULL) || (cp == NULL) || (numBytes == NULL)) {
return GR_IllegalArg;
}
totalBytes = serializeGiantBytes(g);
if(totalBytes == 0) {
*numBytes = 0;
return GR_Success;
}
numDigits = g->sign;
if(totalBytes > *numBytes) {
dbgLog("serializeGiant: Insufficient space\n");
return GR_Overflow;
}
/*
* Emit bytes starting at the far end of the outgoing byte
* stream, which is the l.s. byte of giant data. In order to prevent
* writing out leading zeros, we special case the m.s. digit.
*/
currCp = cp + totalBytes - 1;
for(digitDex=0; digitDex<numDigits - 1; digitDex++) {
/* one loop per giant digit */
digit = g->n[digitDex];
for(digitByte=0; digitByte<GIANT_BYTES_PER_DIGIT; digitByte++) {
/* one loop per byte in the digit */
*currCp-- = (gi_uint8)digit;
digit >>= 8;
}
}
/* Handle the m.s. digit, by writing out only as many bytes as are left.
Since we already wrote out numDigits - 1 digits above the answer is: */
bytesLeft = totalBytes - (numDigits - 1) * GIANT_BYTES_PER_DIGIT;
digit = g->n[digitDex];
for(digitByte=0; digitByte<bytesLeft; digitByte++) {
/* one loop per byte in the digit */
*currCp-- = (gi_uint8)digit;
digit >>= 8;
}
*numBytes = totalBytes;
return GR_Success;
}
/*
* Initialize a giant with specified data. Does not have to be
* aligned to giantDigits (as the output of serializeGiant() always
* is).
*/
GIReturn deserializeGiant(
giant g,
const gi_uint8 *cp,
gi_uint16 numBytes)
{
gi_size numDigits;
giantDigit digit;
giantDigit tempDigit;
gi_size digitDex;
gi_size digitByte;
gi_size dex;
const gi_uint8 *currCp;
GI_CHECK_SP("deserializeGiant");
if(g == NULL) {
return GR_IllegalArg;
}
if(numBytes == 0) {
g->sign = 0;
return GR_Success;
}
if(cp == NULL) {
return GR_IllegalArg;
}
/*
* Trim off leading zeroes, sometimes placed there during DER
* encoding to ensure the number does not appear negative. We
* don't support negative numbers in this module...
*/
while((*cp == 0) && (numBytes != 0)) {
cp++;
numBytes--;
}
if(numBytes == 0) {
g->sign = 0;
return GR_Success;
}
numDigits = BYTES_TO_GIANT_DIGITS(numBytes);
if(numDigits > g->capacity) {
return GR_Overflow;
}
/*
* Start at l.s. byte, at the far end of the byte stream.
*/
digitDex = 0; /* index into g->n[] */
digit = 0; /* accumulator */
digitByte = 0; /* byte index into digit */
currCp = cp + numBytes - 1;
for(dex=0; dex<numBytes; dex++) {
/* add in current byte */
tempDigit = *currCp--;
tempDigit <<= (8 * digitByte);
digit |= tempDigit;
digitByte++;
/* have a complete digit, or reached the last byte? */
if((digitByte == GIANT_BYTES_PER_DIGIT) || /* full digit */
(dex == (numBytes - 1))) { /* no more data */
g->n[digitDex++] = digit;
/* reset for next digit */
digit = 0;
digitByte = 0;
}
}
/*
* Infer sign/size from non-zero n[] elements
*/
g->sign = numDigits;
gtrimSign(g);
return GR_Success;
}
+59
View File
@@ -0,0 +1,59 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* giantExternal.h - convert between giant integer and external representation
*
* Created Aug. 5 2005 by Doug Mitchell.
*/
#ifndef _GIANT_EXTERNAL_H_
#define _GIANT_EXTERNAL_H_
#include <libGiants/giantIntegers.h>
#include <libGiants/giantTypes.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Max size in bytes needed to serialize a giant of given number of digits.
*/
#define MAX_SERIALIZED_GIANT_SIZE(digits) (GIANT_BYTES_PER_DIGIT * digits)
/*
* Precalculate actual size in bytes needed to serialize a given giant.
*/
gi_uint16 serializeGiantBytes(const giant g);
/*
* serialize, deserialize giants's n[] to/from byte stream.
* First byte of byte stream is the m.s. byte of the resulting giant,
* regardless of the size of giantDigit. The resulting byte stream
* is suitable for use as the content of a DER-encoded integer.
*
* No assumption is made about the alignment of cp.
*
* The numBytes argument indicates the space available on input;
* on return it indicates the actual number of bytes written.
*/
GIReturn serializeGiant(
const giant g,
gi_uint8 *cp,
gi_uint16 *numBytes); /* IN/OUT */
/*
* Initialize a giant with specified data, which may well have come from
* serializeGiant.
*/
GIReturn deserializeGiant(
giant g,
const gi_uint8 *cp,
gi_uint16 numBytes);
#ifdef __cplusplus
}
#endif
#endif /* _GIANT_EXTERNAL_H_ */
File diff suppressed because it is too large. Load diff
+286
View File
@@ -0,0 +1,286 @@
/* Copyright (c) 1998-2007 Apple Inc. All Rights Reserved.
*
* NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT
* TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE
* SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE
* ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER,
* INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL
* EXPOSE YOU TO LIABILITY.
***************************************************************************
*
* giantIntegers.h - large-integer arithmetic library.
*/
#ifndef _GI_GIANTINTEGERS_H_
#define _GI_GIANTINTEGERS_H_
#include <libGiants/giantTypes.h>
#include <libGiants/giantDebug.h>
#ifdef __cplusplus
extern "C" {
#endif
/* platform-independent digit manipulation macros */
#define GIANT_BYTES_PER_DIGIT (sizeof(giantDigit))
#define GIANT_BITS_PER_DIGIT (8 * GIANT_BYTES_PER_DIGIT)
#define GIANT_DIGIT_MASK ((giantDigit)~0)
#define BYTES_TO_GIANT_DIGITS(x) \
((x + GIANT_BYTES_PER_DIGIT - 1) / GIANT_BYTES_PER_DIGIT)
/*
* Static giant support; giantstruct->n[] no longer dynamically allocated, but
* hard-coded to the max needed for a particular implementation. This max size
* is a function of the prime size (easy to determine) and the max size of
* giant, in digits relative to the size of the prime, actually needed for the
* math implemented in this library (which is going to be tricky to accurately
* determine). We want to minimize the static size of a giant in order to
* minimize RAM usage.
*/
#ifndef GI_MAX_PRIME_SIZE_BITS
#error Please #define GI_MAX_PRIME_SIZE_BITS.
#endif
/* convert that to bytes and digits; these remain fixed */
#define MAX_PRIME_SIZE_BYTES ((GI_MAX_PRIME_SIZE_BITS + 7) / 8)
#define MAX_PRIME_SIZE_DIGITS BYTES_TO_GIANT_DIGITS(MAX_PRIME_SIZE_BYTES)
/*
* The number of digits in a minimal giant, requiring only extra space for
* an add.
*/
#define GIANT_LITTLE_DIGITS (MAX_PRIME_SIZE_DIGITS + 1)
/*
* The number of digits in a max giant, used for mulg and its kin.
*/
#define GIANT_BIG_DIGITS (MAX_PRIME_SIZE_DIGITS * 2)
/*
* The number of digits in a "triple giant", used sparingly in and
* around make_recip and modg_via_recip only.
* The max observed required size seems to be when doing a mulg on
* two numbers, both of whose signs are s+1.
*/
#define GIANT_TRIPLE_DIGITS ((MAX_PRIME_SIZE_DIGITS * 2) + 2)
/* Basic giant type with giantDigit array allocated elsewhere */
typedef struct {
gi_uint16 sign; /* number of giantDigits */
gi_uint16 capacity; /* largest possible number of giantDigits */
giantDigit *n; /* n[0] is l.s. digit */
} giantStruct;
typedef giantStruct *giant;
/*
* Giant capable of being allocated on the stack, with capacity
* no greater than GIANT_LITTLE_DIGITS, i.e., a "little giant" or
* lGiant in the SFEE paper.
*
* Use base giantstruct g in any function call requiring a giant.
*/
typedef struct {
giantStruct g;
giantDigit _n_[GIANT_LITTLE_DIGITS];
} lgiant;
/*
* "Big giant" "subclass" of standard giant. Use base giantstruct g in
* any function call requiring a giant.
*/
typedef struct {
giantStruct g;
giantDigit _n_[GIANT_BIG_DIGITS];
} bigGiantStruct;
typedef bigGiantStruct bgiant; /* for heap allocation */
/*
* "Triple giant" "subclass" of standard giant. Used sparingly in and
* around make_recip only.
*/
typedef struct {
giantStruct g;
giantDigit _n_[GIANT_TRIPLE_DIGITS];
} tripleGiantStruct;
typedef tripleGiantStruct tgiant;
gi_uint16 bitlen(giant n); /* Returns the bit-length n;
* e.g. n=7 returns 3. */
giantDigit bitval(giant n, gi_uint16 pos);
gi_uint16 giantNumBytes(giant n);
void gtog(giant src, giant dest); /* Copies one giant to another */
void int_to_giant(gi_uint32 n, giant g); /* Gives a giant an int value */
GIReturn giant_to_int(giant g, gi_uint32 *i); /* Convent giant to int. */
gi_uint16 numtrailzeros(giant g); /* # of trailing zero bits in g */
int gcompg(giant a, giant b); /* Returns 1, 0, -1 as a>b, a=b, a<b */
void normal_addg(giant a, giant b); /* b += a */
#define addg(a, b) normal_addg(a, b)
void iaddg(giantDigit a, giant b); /* b += a */
void imulg(giantDigit a, giant b); /* b *= a */
void normal_subg(giant a, giant b); /* b -= a. */
void gshiftleft(gi_uint16 bits, giant g); /* Shift g left by bits, introducing
* zeros on the right. */
void gshiftright(gi_uint16 bits, giant g); /* Shift g right by bits, losing bits
* on the right. */
// Right-shift z by s giantDigits
void gshifltwordsright(gi_uint16 digits, giant g);
// shift left by s giantDigits
void gshiftwordsleft(gi_uint16 digits, giant g);
void extractbits(gi_uint16 n, giant src, giant dest);
/* dest becomes lowermost n bits of
* src. Equivalent to
* dest = src % 2^n */
void grammarSquare(giant a); /* g *= g. */
void grammarSquare_common(giant a, giant dest);
/* dest := (a * a)
* dest is typically a bgiant */
#define gsquare(g) grammarSquare(g)
void mulg(giant a, giant b); /* b *= a. */
void mulg_common(giant a, giant b, giant dest);
/* dest := a * b;
* dest is typically a bgiant */
void gtrimSign(giant g); /* Adjust sign for possible leading
* (m.s.) zero digits */
void clearGiant(giant g); /* zero a giant's data */
/* converted from trivial functions */
#if GIANTS_DEBUG
/*
* counter, acccumulates calls to (giantDigit x giantDigit) multiply.
*/
extern unsigned numGiantDigitMuls;
#define INCR_DIGIT_MULS numGiantDigitMuls++
/*
* Accumulate calls to mulg_common()
*/
extern unsigned numMulgCommon;
#define INCR_NUM_MULGS numMulgCommon++;
/*
* Accumulate calls to grammarSquare_common()
*/
extern unsigned numGSquareCommon;
#define INCR_NUM_GSQUARE numGSquareCommon++;
#else /* GIANTS_DEBUG */
#define INCR_DIGIT_MULS
#define INCR_NUM_MULGS
#define INCR_NUM_GSQUARE
#endif /* GIANTS_DEBUG */
/*
* Functions which can be explicit C functions, macros, or static inlines
* depending on the configuration.
*/
#if !defined(GI_INLINE_SMALL_FUNCS) && !defined(GI_MACRO_SMALL_FUNCTIONS)
#error Please define GI_INLINE_SMALL_FUNCS and GI_MACRO_SMALL_FUNCTIONS.
#endif
#if GI_INLINE_SMALL_FUNCS && GI_MACRO_SMALL_FUNCTIONS
#error GI_INLINE_SMALL_FUNCS and GI_MACRO_SMALL_FUNCTIONS are mutually exclusive.
#endif
#if GI_INLINE_SMALL_FUNCS
/* common giant init */
static GI_INLINE void initGiant(
giant g,
gi_uint16 capacity,
giantDigit *digits)
{
g->sign = 0;
g->capacity = capacity;
g->n = digits;
}
/* call this after declaring a local lgiant and before using it */
static GI_INLINE void localGiantAlloc(lgiant *g)
{
initGiant(&g->g, GIANT_LITTLE_DIGITS, g->_n_);
}
/* ditto, for a bgiant */
static GI_INLINE void localBigGiantAlloc(bgiant *g)
{
initGiant(&g->g, GIANT_BIG_DIGITS, g->_n_);
}
/* ditto, for a tgiant */
static GI_INLINE void localTriGiantAlloc(tgiant *g)
{
initGiant(&g->g, GIANT_TRIPLE_DIGITS, g->_n_);
}
/* Returns whether g is 1 */
static GI_INLINE int isone(giant g)
{
return ((g->sign == 1) && (g->n[0] == 1));
}
/* Returns whether g is zero */
static GI_INLINE int isZero(giant g)
{
/* we're skipping the !trimmed check here... */
return (g->sign == 0);
}
#elif GI_MACRO_SMALL_FUNCTIONS
#define initGiant(gnt, cap, digs) \
(gnt)->sign = 0; \
(gnt)->capacity = cap; \
(gnt)->n = digs;
#define localGiantAlloc(lg) initGiant(&((lg)->g), GIANT_LITTLE_DIGITS, (lg)->_n_)
#define localBigGiantAlloc(bg) initGiant(&((bg)->g), GIANT_BIG_DIGITS, (bg)->_n_)
#define localTriGiantAlloc(tg) initGiant(&((tg)->g), GIANT_TRIPLE_DIGITS, (tg)->_n_)
#define isone(g) (((g)->sign == 1) && ((g)->n[0] == 1))
#define isZero(g) ((g)->sign == 0)
#else
/*** regular C functions ***/
/* call this after declaring a local lgiant and before using it */
extern void localGiantAlloc(lgiant *g);
/* ditto, for a bgiant */
extern void localBigGiantAlloc(bgiant *g);
/* ditto, for a tgiant */
extern void localTriGiantAlloc(tgiant *g);
void initGiant(
giant g,
gi_uint16 capacity,
giantDigit *digits);
int isone(giant g); /* Returns whether g is 1 */
int isZero(giant g); /* Returns whether g is zero */
#endif /* INLINE / MACRO */
#ifdef __cplusplus
}
#endif
#endif /* _GI_GIANTINTEGERS_H_ */
+48
View File
@@ -0,0 +1,48 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* giantMemutils.c - trivial implementation of memcpy and bzero, for platforms
* without libc versions of those functions.
*
* Created Aug. 8 2005 by Doug Mitchell.
*/
#include <libGiants/giantPlatform.h>
#ifndef GI_HAVE_MEMCPY
#error Please define GI_HAVE_MEMCPY.
#endif
#ifndef GI_HAVE_BZERO
#error Please define GI_HAVE_BZERO.
#endif
#if !GI_HAVE_MEMCPY
void *Memcpy(void *dst, const void *src, gi_uint16 len)
{
gi_size dex;
unsigned char *dstp = (unsigned char *)dst;
const unsigned char *srcp = (const unsigned char *)src;
for(dex=0; dex<len; dex++) {
*dstp++ = *srcp++;
}
return dst;
}
#endif
#if !GI_HAVE_BZERO
void Bzero(void *b, gi_uint16 len)
{
gi_size dex;
unsigned char *dstp = (unsigned char *)b;
for(dex=0; dex<len; dex++) {
*dstp++ = 0;
}
}
#endif
+722
View File
@@ -0,0 +1,722 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* giantMod.c - modular arithmetic function declarations.
*
* Created Nov. 29 2005 by Doug Mitchell.
*/
#include <libGiants/giantMod.h>
#include <libGiants/giantDebug.h>
#ifndef GI_SMALL_CRT_ENABLE
#error Please define GI_SMALL_CRT_ENABLE.
#endif
#if GI_SMALL_CRT_ENABLE
/*
* Custom version of the tgiant for GI_SMALL_CRT_ENABLE use.
* Normally a tgiant has 2n+2 digits. The corresponding "small tgiant"
* has n+2 digits.
*/
#define GIANT_SMALL_TRIPLE_DIGITS (MAX_PRIME_SIZE_DIGITS + 2)
typedef struct {
giantStruct g;
giantDigit _n_[GIANT_SMALL_TRIPLE_DIGITS];
} smallTGiantStruct;
typedef smallTGiantStruct stgiant;
static GI_INLINE void localSmallTGiantAlloc(stgiant *g)
{
initGiant(&g->g, GIANT_SMALL_TRIPLE_DIGITS, g->_n_);
}
static void rsquareSmall(
giant x,
giant n,
giant recip);
static void rmulgSmall(
giant x,
giant y,
giant n,
giant recip);
static void modg_via_recipSmall(
giant d,
giant r,
giant n);
static void powermodgSmall(
giant base,
giant expo,
giant n,
giant recip,
giant result);
#endif
/* for lots of grungy low-level debugging */
#define DEBUG_MODG 0
#if DEBUG_MODG
#include <stdio.h>
#include <libGiantsUtils/printGiant.h>
static void dispGiant(
const char *label,
giant g)
{
printf("--- %s : ", label);
printGiant(g);
}
static void dispInt(
const char *label,
unsigned i)
{
printf("--- %s : %u\n", label, i);
}
static void dispHeader(
const char *label)
{
printf("--- %s ---\n", label);
}
static void dispDelim(void)
{
printf("-------------\n");
}
#else /* DEBUG_MODG */
#define dispGiant(l, g)
#define dispInt(l, i)
#define dispDelim()
#define dispHeader(l)
#endif /* DEBUG_MODG */
#if GI_MODG_ENABLE
/* returns 1 if g has exactly one bit set, else returns zero */
static int isPowerOfTwo(
giant g)
{
int foundBit = 0;
gi_uint16 dex;
giantDigit currDigit;
giantDigit mask;
GI_CHECK_SP("isPowerOfTwo");
if(isZero(g)) {
return 0;
}
/* see if m.s. digit has exactly one bit set */
currDigit = g->n[g->sign - 1];
/* mask shifts out to zero when done */
for(mask=0x01; mask != 0; mask <<= 1) {
if(currDigit & mask) {
if(foundBit) {
/* found second bit set: done */
return 0;
}
else {
/* first '1' bit seen */
foundBit = 1;
}
}
}
GIASSERT(foundBit != 0);
/* now we return true iff all the rest of the digits are zero */
for(dex=0; dex<g->sign-1; dex++) {
if(g->n[dex] != 0) {
return 0;
}
}
return 1;
}
/*
* Calculate the reciprocal of a demonimator.
*/
void make_recip(
giant d,
giant recip)
/* r becomes the steady-state reciprocal
2^(2b)/d, where b = bit-length of d-1. */
{
int b;
tgiant tmp1;
bgiant tmp2;
tgiant tmp3;
GI_CHECK_SP("make_recip (1)");
if (isZero(d)) {
GIASSERT(0);
return;
}
if(isPowerOfTwo(d)) {
gtog(d, recip);
return;
}
localTriGiantAlloc(&tmp1);
localBigGiantAlloc(&tmp2);
localTriGiantAlloc(&tmp3);
//localGiantAlloc(&tmpRecip);
GI_CHECK_SP("make_recip (2)");
b = bitlen(d);
int_to_giant(1, recip);
if((b & (GIANT_BITS_PER_DIGIT - 1)) == 0) {
/* digit-aligned */
gshiftwordsleft(b >> GI_GIANT_LOG2_BITS_PER_DIGIT, recip);
}
else {
gshiftleft(b, recip);
}
gtog(recip, &tmp2.g);
while(1) {
grammarSquare_common(recip, &tmp1.g);
gshiftright(b, &tmp1.g);
mulg_common(d, &tmp1.g, &tmp3.g);
gshiftright(b, &tmp3.g);
addg(recip, recip);
normal_subg(&tmp3.g, recip);
if(gcompg(recip, &tmp2.g) <= 0) {
break;
}
gtog(recip, &tmp2.g);
}
mulg_common(recip, d, &tmp1.g);
int_to_giant(1, &tmp2.g);
while(bitlen(&tmp1.g) > (2 * b)) {
normal_subg(&tmp2.g, recip);
normal_subg(d, &tmp1.g);
}
CHECK_GIANT_OFLOW(recip);
}
#define MODG_CTR_LIMIT 3
/*
* Optimized modg.
* n := n % d, where r is the precalculated steady-state reciprocal of d.
*/
void modg_via_recip(
giant d,
giant r,
giant n)
{
int s = bitlen(r)-1;
bgiant tmp1;
tgiant tmp2;
//dispGiant("d", d);
//dispGiant("r", r);
//dispGiant("n", n);
GI_CHECK_SP("modg_via_recip(1)");
GIASSERT(!isZero(r));
if(s == 0) {
int_to_giant(0, n);
return;
}
if(gcompg(n, d) < 0) {
/* this mod is a nop: done. */
return;
}
localBigGiantAlloc(&tmp1);
localTriGiantAlloc(&tmp2);
do {
unsigned ct = 0;
gtog(n, &tmp1.g);
gshiftright(s-1, &tmp1.g);
mulg_common(r, &tmp1.g, &tmp2.g);
gshiftright(s+1, &tmp2.g);
mulg_common(d, &tmp2.g, &tmp1.g);
normal_subg(&tmp1.g, n);
while(++ct <= MODG_CTR_LIMIT) {
if(gcompg(n,d) >= 0) {
normal_subg(d,n);
}
else {
return;
}
}
} while(1);
}
/* Both n and div are written by this function, with new values:
n := n mod d,
div := floor(n/d).
*/
void divmodg_via_recip(
giant d,
giant r,
giant n,
giant dv)
{
int s = bitlen(r)-1;
tgiant tmp1;
tgiant tmp2;
GI_CHECK_SP("divmodg_via_recip(1)");
GIASSERT(!isZero(r));
if(s == 0) {
int_to_giant(0, n);
gtog(n, dv);
return;
}
int_to_giant(0, dv);
if(gcompg(n, d) < 0) {
/* this mod is a nop: done. */
return;
}
localTriGiantAlloc(&tmp1);
localTriGiantAlloc(&tmp2);
GI_CHECK_SP("divmodg_via_recip(2)");
do {
unsigned ct = 0;
gtog(n, &tmp1.g);
gshiftright(s-1, &tmp1.g);
mulg_common(r, &tmp1.g, &tmp2.g);
gshiftright(s+1, &tmp2.g);
mulg_common(d, &tmp2.g, &tmp1.g);
normal_subg(&tmp1.g, n);
addg(&tmp2.g, dv);
while(++ct <= 3) {
if(gcompg(n,d) >= 0) {
normal_subg(d,n);
iaddg(1, dv);
}
else {
return;
}
}
} while(1);
}
/* x := (x^2) mod n with known reciprocal of n */
void rsquare(
giant x,
giant n,
giant recip)
{
bgiant sq;
GI_CHECK_SP("rsquare(1)");
localBigGiantAlloc(&sq);
GI_CHECK_SP("rsquare(2)");
grammarSquare_common(x, &sq.g);
modg_via_recip(n, recip, &sq.g);
gtog(&sq.g, x);
}
/* y := (x * y) mod n with known reciprocal of n */
void rmulg(
giant x,
giant y,
giant n,
giant recip)
{
bgiant prod;
GI_CHECK_SP("rmulg");
localBigGiantAlloc(&prod);
mulg_common(x, y, &prod.g);
modg_via_recip(n, recip, &prod.g);
gtog(&prod.g, y);
}
/*
* result becomes base^expo (mod n).
* Caller knows and gives us reciprocal of n as recip.
* base and result can share the same giant.
*/
void powermodg(
giant base,
giant expo,
giant n,
giant recip,
giant result)
{
int len, pos;
lgiant bmod; /* saved base mod n */
GI_CHECK_SP("powermodg");
GI_LOG_SP("top of powermodg");
if(isZero(expo)) {
int_to_giant(1, result);
return;
}
localGiantAlloc(&bmod);
if(base != result) {
gtog(base, result);
}
if(gcompg(result, n) >= 0) {
modg_via_recip(n, recip, result);
}
gtog(result, &bmod.g);
len = bitlen(expo);
if(len == 1) {
return;
}
for(pos = len-2; pos >= 0; pos--) {
rsquare(result, n, recip); // New ring-square.
if (bitval(expo, pos)) {
rmulg(&bmod.g, result, n, recip);
}
}
return;
}
void modg(
giant d,
giant n)
/* n becomes n%d. n is arbitrary, but the denominator d must be positive! */
{
lgiant recip;
GI_CHECK_SP("modg");
localGiantAlloc(&recip);
make_recip(d, &recip.g);
modg_via_recip(d, &recip.g, n);
}
/*
* power/mod using Chinese Remainder Theorem.
*
* result becomes base^d (mod n).
*
* ...but we don't know or need d or n. What we have are
*
* p, q such that n = p*q
* reciprocals of p, q
* dp = d mod (p-1)
* dq = d mod (q-1)
* qinv = q^(1) mod p
*/
void powermodCRT(
giant x, /* base (plaintext/ciphertext) */
giant p, /* p*q = n */
giant pRecip, /* reciprocal of p */
giant q,
giant qRecip, /* reciprocal of p */
giant dp, /* d mod (p-1) */
giant dq, /* d mod (q-1) */
giant qinv,
giant sq, /* scratch, provided and init'd by caller */
giant result) /* OUTPUT */
{
bgiant sp;
int m;
GI_CHECK_SP("powermodCRT");
localBigGiantAlloc(&sp);
GIASSERT(sq->capacity >= GIANT_LITTLE_DIGITS);
/*
* sp := x^dp mod p;
* sq := x^dq mod q;
*/
#if GI_SMALL_CRT_ENABLE
powermodgSmall(x, dp, p, pRecip, &sp.g);
powermodgSmall(x, dq, q, qRecip, sq);
#else
powermodg(x, dp, p, pRecip, &sp.g);
powermodg(x, dq, q, qRecip, sq);
#endif
/*
* m = gcompg(sp, sq);
* if(m > = 0)
* result = sp-sq;
* else
* result = sq-sp; // Note unsigned subtract always;
*/
m = gcompg(&sp.g, sq);
if(m >= 0) {
gtog(&sp.g, result);
normal_subg(sq, result);
}
else {
gtog(sq, result);
normal_subg(&sp.g, result);
}
/*
* result = (qinv * result) mod p;
* done with sp, use as scratch now...
*/
mulg_common(result, qinv, &sp.g);
modg_via_recip(p, pRecip, &sp.g);
gtog(&sp.g, result);
/*
* if( ! isZero(result)) if(m < 0) result = p - result;
*/
if(!isZero(result)) {
if(m < 0) {
gtog(p, &sp.g);
normal_subg(result, &sp.g);
gtog(&sp.g, result);
}
}
/*
* result *= q;
* result += sq;
*/
mulg_common(result, q, &sp.g);
addg(sq, &sp.g);
gtog(&sp.g, result);
}
#endif /* GI_MODG_ENABLE */
#if GI_INVERSE_MOD_ENABLE
/*
* Given x, y coprime with x > 0, y > 1, this routine forces
* x := x^(-1) mod modulus.
*/
void ginverseMod(
giant modulus,
giant recip, /* reciprocal of modulus */
giant x) /* IN/OUT */
{
lgiant u, v, a, q, tmp;
unsigned int k = 0;
lgiant uRecip;
GI_CHECK_SP("ginverseMod");
localGiantAlloc(&u);
localGiantAlloc(&v);
localGiantAlloc(&a);
localGiantAlloc(&q);
localGiantAlloc(&tmp);
localGiantAlloc(&uRecip);
dispHeader("ginverseMod top");
dispGiant("x", x);
dispGiant("modulus", modulus);
dispGiant("recip", recip);
/*
* 1) (u, v, a, x, k) = (x mod modulus, modulus, 0, 1, 0);
*/
gtog(x, &u.g);
modg_via_recip(modulus, recip, &u.g);
gtog(modulus, &v.g);
/* a is already zero */
int_to_giant(1, x);
dispHeader("ginverseMod before loop");
dispGiant("x", x);
dispGiant("u", &u.g);
dispGiant("v", &v.g);
dispGiant("a", &a.g);
dispInt("k", k);
/*
* 2) while(u > 1) {
* q = v div u;
* (u, v, a, x, k) = (v mod u, u, x, (a + q*x) mod y, k + 1);
* }
*/
while(!isZero(&u.g) && !isone(&u.g)) {
/* (q,u) := (v div u, v mod u */
make_recip(&u.g, &uRecip.g);
gtog(&u.g, &tmp.g); /* for a const modulus in divmodg_via_recip() */
gtog(&v.g, &u.g); /* divisor, then result of mod */
divmodg_via_recip(&tmp.g, &uRecip.g, &u.g, &q.g);
/* v := old u */
gtog(&tmp.g, &v.g);
/* intermediate: *old* x */
gtog(x, &tmp.g);
/* calc new x := a + q*x mod y */
rmulg(&q.g, x, modulus, recip);
addg(&a.g, x);
modg_via_recip(modulus, recip, x); /* just in case */
/* new a := old x */
gtog(&tmp.g, &a.g);
k++;
dispDelim();
dispGiant("x", x);
dispGiant("q", &q.g);
dispGiant("u", &u.g);
dispGiant("v", &v.g);
dispGiant("a", &a.g);
dispInt("k", k);
}
/*
* 3) if(k odd) x = y - x; // Unsigned (normal_subg) subtract.
*/
if(k & 1) {
gtog(modulus, &u.g);
normal_subg(x, &u.g);
gtog(&u.g, x);
}
}
#endif /* GI_INVERSE_MOD_ENABLE */
#if GI_SMALL_CRT_ENABLE
/*
* Optional "small giant" routines used only by powermodCRT when
* performing its initial powermodg operations with p and q as the
* modulus; p and q are half the size of MAX_PRIME_SIZE_DIGITS, so
* we implement the following functions with corresponding small
* local giants.
* On PPC, this saves 384 bytes of stack space, at the cost of
* 1407 extra bytes of code.
*/
static void rsquareSmall(
giant x,
giant n,
giant recip)
{
stgiant sq;
GI_CHECK_SP("rsquareSmall(1)");
localSmallTGiantAlloc(&sq);
GI_CHECK_SP("rsquareSmall(2)");
grammarSquare_common(x, &sq.g);
modg_via_recipSmall(n, recip, &sq.g);
gtog(&sq.g, x);
}
/* y := (x * y) mod n with known reciprocal of n */
static void rmulgSmall(
giant x,
giant y,
giant n,
giant recip)
{
stgiant prod;
GI_CHECK_SP("rmulgSmall");
localSmallTGiantAlloc(&prod);
mulg_common(x, y, &prod.g);
modg_via_recipSmall(n, recip, &prod.g);
gtog(&prod.g, y);
}
/*
* Optimized modg.
* n := n % d, where r is the precalculated steady-state reciprocal of d.
*/
static void modg_via_recipSmall(
giant d,
giant r,
giant n)
{
int s = bitlen(r)-1;
stgiant tmp1;
stgiant tmp2;
GI_CHECK_SP("modg_via_recipSmall(1)");
GIASSERT(!isZero(r));
if(s == 0) {
int_to_giant(0, n);
return;
}
if(gcompg(n, d) < 0) {
/* this mod is a nop: done. */
return;
}
localSmallTGiantAlloc(&tmp1);
localSmallTGiantAlloc(&tmp2);
do {
unsigned ct = 0;
gtog(n, &tmp1.g);
gshiftright(s-1, &tmp1.g);
mulg_common(r, &tmp1.g, &tmp2.g);
gshiftright(s+1, &tmp2.g);
mulg_common(d, &tmp2.g, &tmp1.g);
normal_subg(&tmp1.g, n);
while(++ct <= MODG_CTR_LIMIT) {
if(gcompg(n,d) >= 0) {
normal_subg(d,n);
}
else {
return;
}
}
} while(1);
}
/*
* result becomes base^expo (mod n).
* Caller knows and gives us reciprocal of n as recip.
* base and result can share the same giant.
*
* This is only used by powermodCRT, which conveniently hands us
* two initialized scratch giants, one bgiant and one stgiant
* so neither we nor any of our callers have to allocate any
* local giants.
*/
static void powermodgSmall(
giant base,
giant expo,
giant n,
giant recip,
giant result)
{
int len, pos;
lgiant bmod; /* saved base mod n */
GI_CHECK_SP("powermodgSmall");
GI_LOG_SP("top of powermodgSmall");
if(isZero(expo)) {
int_to_giant(1, result);
return;
}
localGiantAlloc(&bmod);
if(base != result) {
gtog(base, result);
}
if(gcompg(result, n) >= 0) {
modg_via_recipSmall(n, recip, result);
}
gtog(result, &bmod.g);
len = bitlen(expo);
if(len == 1) {
return;
}
for(pos = len-2; pos >= 0; pos--) {
rsquareSmall(result, n, recip); // New ring-square.
if (bitval(expo, pos)) {
rmulgSmall(&bmod.g, result, n, recip);
}
}
return;
}
#endif /* GI_SMALL_CRT_ENABLE */
+124
View File
@@ -0,0 +1,124 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* giantMod.h - modular arithmetic function declarations.
*
* Created Nov. 29 2005 by Doug Mitchell.
*/
#ifndef _GIANT_MOD_H_
#define _GIANT_MOD_H_
#include <libGiants/giantIntegers.h>
/* this must be defined in giantPlatform.h */
#ifndef GI_MODG_ENABLE
#error Please define GI_MODG_ENABLE one way or the other.
#endif
#if GI_MODG_ENABLE
#ifdef __cplusplus
extern "C" {
#endif
/*
* Calculate the reciprocal of a demonimator to be used in
* modg_via_recip().
*/
void make_recip(giant d, giant recip);
/*
* n := n % d, where r is the precalculated
* steady-state reciprocal of d.
*/
void modg_via_recip(
giant d,
giant r,
giant n);
/* Both n and div are written by this function, with new values:
n := n mod d,
div := floor(n/d).
*/
void divmodg_via_recip(
giant d,
giant r,
giant n,
giant dv);
/* x := (x^2) mod n with known reciprocal of n */
void rsquare(
giant x,
giant n,
giant recip);
/* y := (x * y) mod n with known reciprocal of n */
void rmulg(
giant x,
giant y,
giant n,
giant recip);
/*
* result becomes base^expo (mod n).
* Caller knows and gives us reciprocal of n as recip.
* base and result can share the same giant.
*/
void powermodg(
giant base,
giant expo,
giant n,
giant recip,
giant result);
/* n becomes n%d. n is arbitrary, but the denominator d must be positive! */
void modg(giant d,giant n);
/*
* power/mod using Chinese Remainder Theorem.
*
* result becomes base^d (mod n).
*
* ...but we don't know or need d or n. What we have are
*
* p, q such that n = p*q
* reciprocals of p, q
* dp = d mod (p-1)
* dq = d mod (q-1)
* qinv = q^(1) mod p
*
* Plus one scratch giant, initialized by caller with the capacity at
* least as big as an lgiant.
*
* The base and result arguments can be identical, i.e., an in/out
* parameter.
*/
void powermodCRT(
giant base, /* base (plaintext/ciphertext) */
giant p, /* p*q = n */
giant pRecip, /* reciprocal of p */
giant q,
giant qRecip, /* reciprocal of q */
giant dp, /* d mod (p-1) */
giant dq, /* d mod (q-1) */
giant qinv,
giant scratchLgiant,
giant result); /* OUTPUT */
/*
* Given x, y coprime with x > 0, y > 1, this routine forces
* x := x^(-1) mod y.
*/
void ginverseMod(
giant modulus,
giant recip, /* reciprocal of modulus */
giant x); /* IN/OUT */
#ifdef __cplusplus
}
#endif
#endif /* GI_MODG_ENABLE */
#endif /* _GIANT_MOD_H_ */
+370
View File
@@ -0,0 +1,370 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* giantPlatform.h - platform specific type and routines, must be ported to
* each platform on which this library runs.
*/
#ifndef _GIANT_PLATFORM_H_
#define _GIANT_PLATFORM_H_
/*
* This is defined true only for development and testing.
* For production code, leave it zero and define your platform
* in this file.
*/
#define GI_PLATFORM_EMULATE 1
#if GI_PLATFORM_EMULATE
#include <libGiants/giantPlatformEmulation.h>
#else
/* be sure to #define NDEBUG for deployment builds */
#define NDEBUG
#ifdef NDEBUG
#define GIANTS_DEBUG 0
#else
#define GIANTS_DEBUG 1
#endif
/*
* Machine-dependent word-size related integer types.
*
* The following integer types must be defined in this module:
*
* gi_uint8 -- unsigned 8 bit (typically "unsigned char")
* gi_uint16 -- unsigned 16 bit, platform/compiler dependent
* gi_uint32 -- unsigned 32-bit integer, platform/compiler dependent
* gi_size -- unsigned, at *least* 16 bits. Could be larger if that's
* more efficient for the platform. For example on a 32-bit
* processor this should be an unsigned 32 bit integer.
* Generally used inside of functions as counters, indices,
* etc. Function parameters which must be portable to
* small processors are expressed as gi_uint16 or
* gi_uint32.
* giantDigit -- see below
* giantDouble -- two giant digits, the result of a giantDigit multiply
*
* giantDigit is the largest native word size for which
* a (giantDigit x giantDigit) hardware multiply (into a giantDouble,
* somehow) is available. This is a crucial data type; the large integer
* artithmetic package uses data types called 'giants' which are mainly
* comprised of arrays of giantDigits. Most of the CPU cycles spent in this
* library are involved in performing arithmetic on these arrays of
* giantDigits.
*
* Our assumption is that the following all always fit into a gi_uint16:
*
* number of bits per giant digit
* number of giant digits in the max base prime in this module
* number of bits in the max base prime in this module
*
* Note we also assume the existence of a 16-bit integer type; arithmetic
* involving this type doesn't have to be particularly fast but it has to be
* usable as a function argument and in simple assignments. Thus 8-bit
* platforms can run this code as long as there is a C type which compiles
* to 16 bits.
*
* These preprocessor symbols also need to be defined for each platform:
*
* GI_GIANT_LOG2_BITS_PER_DIGIT
* The log to base 2 of the size of giantDigit. There
* is no straightforward way for the C preprocessor to figure this one
* out so you have to specify it. For 16-bit giantDigits the value of
* this symbol is 4; for 32-bit giantDigits the value is 5.
*
* GI_GIANT_PORT_INLINE
* 1 : we don't have a platform-specific giant arithmetic module; use the
* inlines in giantPort_Generic.h
* 0 : we have a platform-specific giant arithmetic module
*
* GI_INLINE_SMALL_FUNCS
* 1 : Use 'static inline' for a select set of small (1-3 line) functions.
* Trade more code for faster runtime and less stack usage. The specific
* effect of this flag wil be nighly dependent on your compiler; in some
* cases you might even see smaller code size when this flag is true.
* 0 : Disable this feature, use actual C functions.
*
* GI_MACRO_SMALL_FUNCTIONS
*
* Like GI_INLINE_SMALL_FUNCS, except causes small functions to be implemented
* as macros. For platforms that don't support the 'inline' keyword. Mutually
* exclusive with GI_INLINE_SMALL_FUNCS.
* 1 : Use #defined macros for the functions in question.
* 0 : Disable; use actual C functions.
*
*
* GI_SMALL_CRT_ENABLE
*
* This flag involves a tradeoff between code size and stack usage in the
* giantMod.c module. Setting this flag true increases code size and
* decreases stack usage.
*
* On a G4, the tradeoff is that setting this flag saves 384 bytes of
* stack space, at the cost of 1407 extra bytes of code.
*
* Note: this flag has no effect if GI_MODG_ENABLE is 0.
*
* 0 : disable the small-CRT functions to save code space.
* 1 : enable to the small-CRT functions to save stack space.
*
* GI_HAVE_MEMCPY
* 1 : This platform has memcpy() and we want to use it as the implementation
* of Memcpy()
* 0 : We've provided our own Memcpy()
*
* GI_HAVE_BZERO
* 1 : This platform has bzero() and we want to use it as the implementation
* of Bzero()
* 0 : We've provided our own Bzero()
*
* GI_INLINE
* Used where the 'inline' keyword would normally be used. #define to 'inline'
* if your compiler provides this functionality, else #define it to nothing or
* some other compiler-specific value.
*
* GI_MODG_ENABLE
*
* When nonzero, enables the modular arithmetic functions found in
* giantMod.[ch]. Some applications such as SFEE do not need these functions.
* Other applications, like RSA and BBS, do in fact need them.
*
* 1 : Enable compilation of giantMod.[ch]
* 0 : Disable compilation of giantMod.[ch]
*
* GI_PRIME_TEST_ENABLE
*
* When nonzero, enables the logic in giantPrime.c used to determine
* whether a given giant is prime. Used in RSA key generation.
*
* 1 : Enable compilation of giantPrime.[ch]
* 0 : Disable compilation of giantPrime.[ch]
*
* GI_INVERSE_MOD_ENABLE
*
* When nonzero, enables the ginverseMod() function in giantMod.[ch]. Used
* for RSA key generation and for BBS.
*
* 1 : Enable compilation of ginverseMod()
* 0 : Disable compilation of ginverseMod()
*
*
* Optimization flags
* ------------------
*
* The following symbols have to be #defined to 0 or 1. See the comments below
* for detailed descritpions of the effects of these flags.
*
* GI_GSQUARE_ENABLE
* GI_OPTIMIZED_MULG
* GI_ADDG_INLINE
*/
/* These define a 16-bit word size emulated on Mac OS X */
#include <stdint.h>
typedef unsigned char gi_uint8;
typedef uint16_t gi_uint16;
typedef uint32_t gi_uint32;
typedef uint16_t gi_size;
typedef uint16_t giantDigit;
typedef uint32_t giantDouble; /* two giant digits */
#define GI_GIANT_LOG2_BITS_PER_DIGIT 4
/*
* Maximum size in bits of base integer in this package. For BBS, this is the
* size of the public 'n' parameter. For asymmetric encryption, it's the
* size of the base prime.
*
* Altering this has no effect on performance, only on memory usage.
* Specifically it affects the amount of stack space used (since all
* giantIntegers in this package are allocated on the stack).
*/
#define GI_MAX_PRIME_SIZE_BITS 4096
/****
**** Optimization flags
****/
/*
* Sample measurements of the effects of these flags were
* taken on an 800 MHz G4, with a 16 bit giantDigit, running
* the bbsProtocol test with 1024 bit 'n' and 10000 iterations.
* Your mileage will certainly vary; the only way to know for
* sure which is the best value for a particular optimizatiaon
* flag is to measure a real-world case on your platform and then
* make the size-vs.-speed tradeoff decision yourself.
*
* However, in the meantime, all of the functionality in this
* library does work correctly for any value of all of these
* flags.
*/
/*
* GI_GSQUARE_ENABLE
*
* Set nonzero to disable optimized grammarSquare().
* Setting nonzero increases code size and increases performance.
*
* Setting this true has the following effects (on 800 MHz G4):
*
* -- adds 384 bytes of code
* -- 7% speedup on private side
* -- 7% speedup on public side
*/
#define GI_GSQUARE_ENABLE 1
/*
* GI_OPTIMIZED_MULG
*
* Use old unoptimized, but smaller, mulg if this is zero.
* Setting nonzero increases code size and increases performance.
*
* Setting this true has the following effects (on 800 MHz G4):
*
* -- adds 168 bytes of code
* -- 20% speedup on private side
* -- 18% speedup on public side
*/
#define GI_OPTIMIZED_MULG 1
/*
* GI_ADDG_INLINE
*
* There are two implementations of some core arithmetic routines.
* Which one is faster depends highly on your implementation of the
* routines declared in giantPortCommon.h and implemented in either
* giantPort_Generic.h (as static inlines) or elsewhere (in C or
* possibly assembly language). Performance also depends on your
* platform's giantDouble performance. If giantDouble arithmetic
* is fast then use GI_ADDG_INLINE. Otherwise try !GI_ADDG_INLINE,
* measure the two, and pick the best one.
*
* Setting this false has the following effects (on 800 MHz G4):
*
* -- increases code size 192 bytes
* -- elliptic operations (SFEE) slow down by 50-100%
*/
#define GI_ADDG_INLINE 1
/*
* GI_GIANT_PORT_INLINE
*
* true : we don't have a platform-specific giant arithmetic module
* false : we do
*
* If GI_ADDG_INLINE is true, setting this true saves a small amount
* of code with no measurable performance impact.
*
* If GI_ADDG_INLINE is false, setting GI_GIANT_PORT_INLINE to
* true has the following effects:
*
* -- adds 168 bytes of code
* -- 2% speedup on private side
* -- 1% speedup on public side
*/
#define GI_GIANT_PORT_INLINE 0
/*
* GI_INLINE_SMALL_FUNCS
*
* When true, uses macros instead of a small number of small functions.
* This is a tradeff of speed and less stack usage vs. code size.
*/
#define GI_INLINE_SMALL_FUNCS 1
/*
* GI_MACRO_SMALL_FUNCTIONS
*
* Like GI_INLINE_SMALL_FUNCS, except causes small functions to be implemented
* as macros. For platforms that don't support the 'inline' keyword.
*/
#define GI_MACRO_SMALL_FUNCTIONS 0
/*
* GI_SMALL_CRT_ENABLE
*
* This flag involves a tradeoff between code size and stack usage in the
* giantMod.c module. Setting this flag true increases code size and
* decreases stack usage.
*
* On a G4, the tradeoff is that setting this flag saves 384 bytes of
* stack space, at the cost of 1407 extra bytes of code.
*
* Note: this flag has no effect if GI_MODG_ENABLE is 0.
*/
#define GI_SMALL_CRT_ENABLE 1
/****
**** Library implementation flags
****/
/* standard library functions available here */
#define GI_HAVE_MEMCPY 1
#define GI_HAVE_BZERO 1
/* enable/disable modular arithmetic */
#define GI_MODG_ENABLE 1
/* enable/disable giantPrime.[ch] - requires GI_MODG_ENABLE! */
#define GI_PRIME_TEST_ENABLE 1
/* enable/disable ginverseMod() */
#define GI_INVERSE_MOD_ENABLE 1
#endif /* GI_PLATFORM_EMULATE */
#pragma mark --- Declarations of functions with platform-specific implementations ---
/*
* You should not have to modify the rest of this file.
*/
#if GI_HAVE_MEMCPY || GI_HAVE_BZERO
#include <string.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*
* This platform supports inline keywords.
*/
#define GI_INLINE inline
#if GI_HAVE_MEMCPY
#define Memcpy(d, s, l) memcpy(d, s, l)
#else /* !GI_HAVE_MEMCPY */
/*
* memcpy() equivalent
*/
extern void *Memcpy(void *dst, const void *src, gi_uint16 len);
#endif /* GI_HAVE_MEMCPY */
#if GI_HAVE_BZERO
#define Bzero(b, l) bzero(b, l)
#else /* !GI_HAVE_BZERO */
/*
* bzero() equivalent
*/
extern void Bzero(void *b, gi_uint16 len);
#endif /* GI_HAVE_BZERO */
#ifdef __cplusplus
}
#endif
#endif /*_GIANT_PLATFORM_H_*/
+181
View File
@@ -0,0 +1,181 @@
/* Copyright (c) 2004,2006-2007 Apple Inc. All Rights Reserved.
*
* NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT
* TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE
* SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE
* ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER,
* INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL
* EXPOSE YOU TO LIABILITY.
***************************************************************************
*
* giantPlatformEmulation.h - #defines for platform emulation.
*
* This file is NOT used in production code.
*/
#ifndef _GIANT_PLATFORM_EMULATION_H_
#define _GIANT_PLATFORM_EMULATION_H_
#define NDEBUG
#ifdef NDEBUG
#define GIANTS_DEBUG 0
#else
#define GIANTS_DEBUG 1
#endif
/*
* Emulation targets:
*
* #define _FEE_CUSTOM_XXX_CONFIG_ to 1 and fill in these blanks if
* you want to generate a test configuration which is not strictly related
* to the machine you're building for - e.g., build a 16-bit giant package on PPC.
*/
/* this one for emulating 16-bit CPU on Mac OS X / PPC */
#define _FEE_CUSTOM_16_CONFIG_ 1
/* this one for emulating 8-bit CPU on Mac OS X / PPC */
#define _FEE_CUSTOM_8_CONFIG_ 0
#if _FEE_CUSTOM_16_CONFIG_
/* 16-bit word size emulated on Mac OS X */
#include <stdint.h>
typedef unsigned char gi_uint8;
typedef uint16_t gi_uint16;
typedef uint32_t gi_uint32;
typedef uint16_t gi_size;
typedef uint16_t giantDigit;
typedef uint32_t giantDouble; /* two giant digits */
#define GI_GIANT_LOG2_BITS_PER_DIGIT 4
#elif _FEE_CUSTOM_8_CONFIG_
/* 8-bit word size emulated on Mac OS X */
#include <stdint.h>
typedef unsigned char gi_uint8;
typedef uint16_t gi_uint16;
typedef uint32_t gi_uint32;
typedef uint16_t gi_size;
typedef uint8_t giantDigit;
typedef uint16_t giantDouble; /* two giant digits */
#define GI_GIANT_LOG2_BITS_PER_DIGIT 3
#elif defined(__APPLE__) && defined(__ppc__)
/*
* Mac OS X on 32-bit PPC
*/
#include <stdint.h>
typedef unsigned char gi_uint8;
typedef uint16_t gi_uint16;
typedef uint32_t gi_uint32;
typedef uint32_t gi_size;
typedef uint32_t giantDigit;
typedef uint64_t giantDouble; /* two giant digits */
#define GI_GIANT_LOG2_BITS_PER_DIGIT 5
#elif defined(__APPLE__) && defined(__i386__)
/*
* Mac OS X on 32-bit Pentium
*/
#include <stdint.h>
typedef unsigned char gi_uint8;
typedef uint16_t gi_uint16;
typedef uint32_t gi_uint32;
typedef uint32_t gi_size;
typedef uint32_t giantDigit;
typedef uint64_t giantDouble; /* two giant digits */
#define GI_GIANT_LOG2_BITS_PER_DIGIT 5
#else
/*
* Other target goes here.
*/
#error Platform dependent work needed
#endif
/*
* Maximum size in bits of base integer in this package. For BBS, this is the
* size of the public 'n' parameter.
*/
#define GI_MAX_PRIME_SIZE_BITS 4096
/****
**** Optimization flags
****/
/*
* There are two implementations of some core arithmetic routines.
* Which one is faster depends highly on your implementation of the
* routines declared in giantPortCommon.h and implemented in either
* giantPort_Generic.h (as static inlines) or elsewhere (in C or
* possibly assembly language). Performance also depends on your
* platform's giantDouble performance. If giantDouble arithmetic
* is fast then use GI_ADDG_INLINE. Otherwise try !GI_ADDG_INLINE,
* measure the two, and pick the best one.
*/
#define GI_ADDG_INLINE 1
/*
* true : we don't have a platform-specific giant arithmetic module
* false : we do
*/
#define GI_GIANT_PORT_INLINE 1
/*
* GI_INLINE_SMALL_FUNCS
*
* When true, uses inlines instead of a small number of small functions.
* This is a tradeff of speed and less stack usage vs. code size.
*/
#define GI_INLINE_SMALL_FUNCS 1
/*
* GI_MACRO_SMALL_FUNCTIONS
*
* Like GI_INLINE_SMALL_FUNCS, except causes small functions to be implemented
* as macros. For platforms that don't support the 'inline' keyword.
*/
#define GI_MACRO_SMALL_FUNCTIONS 0
/*
* GI_SMALL_CRT_ENABLE
*
* This flag involves a tradeoff between code size and stack usage in the
* giantMod.c module. Setting this flag true increases code size and
* decreases stack usage.
*
* On a G4, the tradeoff is that setting this flag saves 384 bytes of
* stack space, at the cost of 1407 extra bytes of code.
*
* Note: this flag has no effect if GI_MODG_ENABLE is 0.
*/
#define GI_SMALL_CRT_ENABLE 1
/****
**** Library implementation flags
****/
/* standard library functions available here */
#define GI_HAVE_MEMCPY 1
#define GI_HAVE_BZERO 1
/* enable/disable modular arithmetic */
#define GI_MODG_ENABLE 1
/* enable/disable giantPrime.[ch] */
#define GI_PRIME_TEST_ENABLE 1
/* enable/disable ginverseMod() */
#define GI_INVERSE_MOD_ENABLE 1
#endif /* _GIANT_PLATFORM_EMULATION_H_ */
+98
View File
@@ -0,0 +1,98 @@
/* Copyright (c) 1998,2006-2007 Apple Inc. All Rights Reserved.
*
* NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT
* TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE
* SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE
* ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER,
* INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL
* EXPOSE YOU TO LIABILITY.
***************************************************************************
giantPortCommon.h - common header used to specify and access
platform-dependent giant digit routines.
Revision History
----------------
1 Sep 98 Doug Mitchell at Apple
Created.
*******************************/
#ifndef _GIANT_PORT_COMMON_H_
#define _GIANT_PORT_COMMON_H_
#include <libGiants/giantTypes.h>
/*
* This is a platform-dependent symbol that must be defined elsewhere,
* typically in giantPlatform.h.
*/
#ifndef GI_GIANT_PORT_INLINE
#error Please define GI_GIANT_PORT_INLINE.
#endif
#if GI_GIANT_PORT_INLINE
/*
* Vanilla C version using static inlines, should work on any platform,
* though may not be the fastest possible implementation.
*/
#include <libGiants/giantPort_Generic.h>
#else /* GI_GIANT_PORT_INLINE */
/*
* A platform-dependent implementation of these functions is required.
*/
/*
* Add two digits, return sum. Carry bit returned as an out parameter.
*/
extern giantDigit giantAddDigits(
giantDigit dig1,
giantDigit dig2,
giantDigit *carry); /* RETURNED, 0 or 1 */
/*
* Add a single digit value to a double digit accumulator in place.
* Carry out of the MSD of the accumulator is not handled.
*/
extern void giantAddDouble(
giantDigit *accLow, /* IN/OUT */
giantDigit *accHigh, /* IN/OUT */
giantDigit val);
/*
* Subtract a - b, return difference. Borrow bit returned as an out parameter.
*/
extern giantDigit giantSubDigits(
giantDigit a,
giantDigit b,
giantDigit *borrow); /* RETURNED, 0 or 1 */
/*
* Multiply two digits, return two digits.
*/
extern void giantMulDigits(
giantDigit dig1,
giantDigit dig2,
giantDigit *lowProduct, /* RETURNED, low digit */
giantDigit *hiProduct); /* RETURNED, high digit */
#if 0
/* this is not currently used or needed */
/*
* Multiply a vector of giantDigits, candVector, by a single giantDigit,
* plierDigit, adding results into prodVector. Returns m.s. digit from
* final multiply; only candLength digits of *prodVector will be written.
*/
extern giantDigit VectorMultiply(
giantDigit plierDigit,
giantDigit *candVector,
gi_size candLength,
giantDigit *prodVector);
#endif
#endif /* GI_GIANT_PORT_INLINE */
#endif /* _GIANT_PORT_COMMON_H_ */
+143
View File
@@ -0,0 +1,143 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* giantPort_C.h - Generic giant definitions routines, used when
* no platform-specific version is available.
*
* This module works on any size giantDigit up to and including
* the native unsigned int, as long as the platform does indeed
* supply a (2 x giantDigit) unsigned integer, defined (in
* giantPlatform.h) as a giantDouble.
*
* Created Aug. 8 2005 by Doug Mitchell.
*/
#include <libGiants/giantTypes.h>
#include <libGiants/giantIntegers.h>
#include <libGiants/giantPortCommon.h>
#include <libGiants/giantDebug.h>
#ifndef GI_GIANT_PORT_INLINE
#error Please define GI_GIANT_PORT_INLINE.
#endif
#if !GI_GIANT_PORT_INLINE
/*
* Add two digits, return sum. Carry bit returned as an out parameter.
*/
giantDigit giantAddDigits(
giantDigit dig1,
giantDigit dig2,
giantDigit *carry) /* RETURNED, 0 or 1 */
{
giantDigit sum = dig1 + dig2;
GI_CHECK_SP("giantAddDigits");
if((sum < dig1) || (sum < dig2)) {
*carry = 1;
}
else {
*carry = 0;
}
return sum;
}
/*
* Add a single digit value to a double digit accumulator in place.
* Carry out of the MSD of the accumulator is not handled.
*/
void giantAddDouble(
giantDigit *accLow, /* IN/OUT */
giantDigit *accHigh, /* IN/OUT */
giantDigit val)
{
giantDigit sumLo = *accLow + val;
GI_CHECK_SP("giantAddDouble");
if((sumLo < *accLow) || (sumLo < val)) {
(*accHigh)++;
/* if it's zero we just overflowed */
GIASSERT(*accHigh != 0);
}
*accLow = sumLo;
}
/*
* Subtract a - b, return difference. Borrow bit returned as an out parameter.
*/
giantDigit giantSubDigits(
giantDigit a,
giantDigit b,
giantDigit *borrow) /* RETURNED, 0 or 1 */
{
giantDigit diff = a - b;
GI_CHECK_SP("giantSubDigits");
if(a < b) {
*borrow = 1;
}
else {
*borrow = 0;
}
return diff;
}
/*
* Multiply two digits, return two digits.
*/
void giantMulDigits(
giantDigit dig1,
giantDigit dig2,
giantDigit *lowProduct, /* RETURNED, low digit */
giantDigit *hiProduct) /* RETURNED, high digit */
{
giantDouble dprod;
GI_CHECK_SP("giantMulDigits");
dprod = (giantDouble)dig1 * (giantDouble)dig2;
*hiProduct = (giantDigit)(dprod >> GIANT_BITS_PER_DIGIT);
*lowProduct = (giantDigit)dprod;
}
#if 0
/* this is currently unused. */
/*
* Multiply a vector of giantDigits, candVector, by a single giantDigit,
* plierDigit, adding results into prodVector. Returns m.s. digit from
* final multiply; only candLength digits of *prodVector will be written.
*/
giantDigit VectorMultiply(
giantDigit plierDigit,
giantDigit *candVector,
gi_size candLength,
giantDigit *prodVector)
{
gi_size candDex; // index into multiplicandVector
giantDigit lastCarry = 0;
giantDigit prodLo;
giantDigit prodHi;
for(candDex=0; candDex<candLength; ++candDex) {
/*
* prod = *(candVector++) * plierDigit + *prodVector + lastCarry
*/
giantMulDigits(*(candVector++),
plierDigit,
&prodLo,
&prodHi);
giantAddDouble(&prodLo, &prodHi, *prodVector);
giantAddDouble(&prodLo, &prodHi, lastCarry);
/*
* *(destptr++) = prodHi;
* lastCarry = prodLo;
*/
*(prodVector++) = prodLo;
lastCarry = prodHi;
}
return lastCarry;
}
#endif /* 0 - VectorMultiply disabled */
#endif /* !GI_GIANT_PORT_INLINE */
+160
View File
@@ -0,0 +1,160 @@
/* Copyright (c) 1998,2006-2007 Apple Inc. All Rights Reserved.
*
* NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT
* TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE
* SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE
* ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER,
* INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL
* EXPOSE YOU TO LIABILITY.
***************************************************************************
*
* giantPort_Generic.h - Generic giant definitions routines, implemented
* as static inlines, used when no platform-specific version is available.
*
* This module works on any size giantDigit up to and including
* the native unsigned int, as long as the platform does indeed
* supply a (2 x giantDigit) unsigned integer, defined (in
* giantPlatform.h) as a giantDouble.
*
* The module giantPort_C.c is functionaly identical to this
* except that its routines are actual C functions instead of
* inlines.
*
* Revision History
* ----------------
* 06 Apr 1998 Doug Mitchell at Apple
* Created.
*/
#ifndef _GIANT_PORT_GENERIC_H_
#define _GIANT_PORT_GENERIC_H_
#include <libGiants/giantTypes.h>
#include <libGiants/giantIntegers.h>
#include <libGiants/giantDebug.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Add two digits, return sum. Carry bit returned as an out parameter.
*/
static GI_INLINE giantDigit giantAddDigits(
giantDigit dig1,
giantDigit dig2,
giantDigit *carry) /* RETURNED, 0 or 1 */
{
giantDigit sum = dig1 + dig2;
if((sum < dig1) || (sum < dig2)) {
*carry = 1;
}
else {
*carry = 0;
}
return sum;
}
/*
* Add a single digit value to a double digit accumulator in place.
* Carry out of the MSD of the accumulator is not handled.
*/
static GI_INLINE void giantAddDouble(
giantDigit *accLow, /* IN/OUT */
giantDigit *accHigh, /* IN/OUT */
giantDigit val)
{
giantDigit sumLo = *accLow + val;
if((sumLo < *accLow) || (sumLo < val)) {
(*accHigh)++;
/* if it's zero we just overflowed */
GIASSERT(*accHigh != 0);
}
*accLow = sumLo;
}
/*
* Subtract a - b, return difference. Borrow bit returned as an out parameter.
*/
static GI_INLINE giantDigit giantSubDigits(
giantDigit a,
giantDigit b,
giantDigit *borrow) /* RETURNED, 0 or 1 */
{
giantDigit diff = a - b;
if(a < b) {
*borrow = 1;
}
else {
*borrow = 0;
}
return diff;
}
/*
* Multiply two digits, return two digits.
*/
static GI_INLINE void giantMulDigits(
giantDigit dig1,
giantDigit dig2,
giantDigit *lowProduct, /* RETURNED, low digit */
giantDigit *hiProduct) /* RETURNED, high digit */
{
giantDouble dprod;
dprod = (giantDouble)dig1 * (giantDouble)dig2;
*hiProduct = (giantDigit)(dprod >> GIANT_BITS_PER_DIGIT);
*lowProduct = (giantDigit)dprod;
}
#if 0
/* this is not currently used or needed */
/*
* Multiply a vector of giantDigits, candVector, by a single giantDigit,
* plierDigit, adding results into prodVector. Returns m.s. digit from
* final multiply; only candLength digits of *prodVector will be written.
*/
static GI_INLINE giantDigit VectorMultiply(
giantDigit plierDigit,
giantDigit *candVector,
gi_size candLength,
giantDigit *prodVector)
{
gi_size candDex; // index into multiplicandVector
giantDigit lastCarry = 0;
giantDigit prodLo;
giantDigit prodHi;
for(candDex=0; candDex<candLength; ++candDex) {
/*
* prod = *(candVector++) * plierDigit + *prodVector + lastCarry
*/
giantMulDigits(*(candVector++),
plierDigit,
&prodLo,
&prodHi);
giantAddDouble(&prodLo, &prodHi, *prodVector);
giantAddDouble(&prodLo, &prodHi, lastCarry);
/*
* *(destptr++) = prodHi;
* lastCarry = prodLo;
*/
*(prodVector++) = prodLo;
lastCarry = prodHi;
}
return lastCarry;
}
#endif
#ifdef __cplusplus
}
#endif
#endif /*_GIANT_PORT_GENERIC_H_*/
+42
View File
@@ -0,0 +1,42 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* giantTypes.h - Standard typedefs
*
* Created Aug. 5 2005 by Doug Mitchell.
*/
#ifndef _GIANT_TYPES_H_
#define _GIANT_TYPES_H_
#include <libGiants/giantPlatform.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Standard return codes.
*/
typedef enum {
GR_Success = 0,
GR_IllegalArg, /* illegal argument */
GR_Unimplemented, /* unimplemented function */
GR_Internal, /* internal library error */
GR_Overflow, /* caller error, buffer/giant overflow */
} GIReturn;
/*
* We administer the namespace for other libraries' return codes here, so
* all can share a common space.
*/
#define SFEE_RETURN_BASE 1000 /* libSFEE */
#define RSA_RETURN_BASE 2000 /* libgRSA */
#define LIBCERT_RETURN_BASE 3000 /* libCert */
#define DH_RETURN_BASE 4000 /* libgDH */
#ifdef __cplusplus
}
#endif
#endif /* _GIANT_TYPES_H_ */
+25
View File
@@ -0,0 +1,25 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/* GIReturnString.c - convert a GIReturn to a string */
#include <libGiantsUtils/GIReturnString.h>
#include <stdio.h>
const char *GIReturnString(GIReturn grtn)
{
static char unknown[100];
switch(grtn) {
case GR_Success: return "GR_Success";
case GR_IllegalArg: return "GR_IllegalArg";
case GR_Unimplemented: return "GR_Unimplemented";
case GR_Internal: return "GR_Internal";
case GR_Overflow: return "GR_Overflow";
default:
sprintf(unknown, "Uknown Error (%d)", (int)grtn);
return unknown;
}
}
+20
View File
@@ -0,0 +1,20 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/* GIReturnString.h - convert a GIReturn to a string */
#ifndef _GIANT_RETURN_STRING_H_
#define _GIANT_RETURN_STRING_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <libGiants/giantTypes.h>
extern const char *GIReturnString(GIReturn grtn);
#ifdef __cplusplus
}
#endif
#endif /* _GIANT_RETURN_STRING_H_ */
+383
View File
@@ -0,0 +1,383 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* libgRSA.h - public API for RSA library based on libGiants
*
* Created Aug. 9 2005 by Doug Mitchell.
*/
#include <libgRSA/libgRSA.h>
#include <libgRSA/libgRSA_config.h>
#include <libgRSA/rsaPadding.h>
#include <libgRSA/libgRSA_priv.h>
#include <libGiants/giantIntegers.h>
#include <libGiants/giantExternal.h>
#include <libGiants/giantMod.h>
#include <libGiants/giantDebug.h>
#define SIG_DEBUG 0
#if SIG_DEBUG
static void showGiant(const char *label, giant g)
{
printf("%s: ", label);
printGiantHex(g);
}
#else
#define showGiant(l, g)
#endif
#if RSA_PUB_KEY_ENABLE
/* lazy evaluation RSAPubGiantKey->recip */
static void rsaEnsurePubRecip(
RSAPubGiantKey *pubKey)
{
GI_CHECK_SP("rsaEnsurePubRecip");
if(pubKey->recip.g.sign != 0) {
return;
}
GI_LOG_SP("rsaEnsurePubRecip calling make_recip");
make_recip(&pubKey->n.g, &pubKey->recip.g);
}
#endif /* RSA_PUB_KEY_ENABLE */
#if RSA_PRIV_KEY_ENABLE
/* lazy evaluation RSAPrivGiantKey->{pRecip,qRecip} */
static void rsaEnsurePrivRecip(
RSAPrivGiantKey *privKey)
{
GI_CHECK_SP("rsaEnsurePrivRecip");
if(privKey->pRecip.g.sign != 0) {
return;
}
GI_LOG_SP("rsaEnsurePrivbRecip calling make_recip");
make_recip(&privKey->p.g, &privKey->pRecip.g);
make_recip(&privKey->q.g, &privKey->qRecip.g);
}
#endif /* RSA_PRIV_KEY_ENABLE */
#if RSA_SIGN_ENABLE
RSAStatus RSA_Sign(
RSAPrivGiantKey *privKey, /* private key */
RSAPadding padding, /* RP_None or RP_PKCS1 */
const gi_uint8 *dataToSign, /* signature over this data */
gi_uint16 dataToSignLen, /* length of dataToSign */
#if RSA_SIG_SHARE_GIANT
RSASignBuffer *signBuffer, /* signature RETURNED here */
#else
gi_uint8 *sig, /* signature, RETURNED */
#endif
gi_uint16 *sigLen) /* IN/OUT if !RSA_SIG_SHARE_GIANT */
/* OUT only if RSA_SIG_SHARE_GIANT */
{
RSAStatus rtn = RSA_Success;
lgiant ptSigGiant; /* in/out for powermodCRT */
gi_uint16 modSize;
GIReturn grtn;
#if !RSA_SIG_SHARE_GIANT
/* powermodCRT needs this one way or another */
lgiant powermodScratch;
#endif
if((dataToSign == NULL) || (sigLen == NULL) || (privKey == NULL)) {
return RSA_ParamErr;
}
#if RSA_SIG_SHARE_GIANT
if(signBuffer == NULL) {
return RSA_ParamErr;
}
#else
if(sig == NULL) {
return RSA_ParamErr;
}
localGiantAlloc(&powermodScratch);
#endif /* RSA_SIG_SHARE_GIANT */
GI_CHECK_SP("RSA_Sign");
localGiantAlloc(&ptSigGiant);
rsaEnsurePrivRecip(privKey);
modSize = ((bitlen(&privKey->p.g) + bitlen(&privKey->q.g)) + 7) / 8;
switch(padding) {
case RP_None:
rtn = rsaAddNoPadding(dataToSign, dataToSignLen, &ptSigGiant.g);
break;
#if RSA_PADDING_PKCS1_ENABLE
case RP_PKCS1:
rtn = rsaAddPkcs1Padding(dataToSign, dataToSignLen,
modSize, RSA_PKCS1_PAD_SIGN,
NULL, /* no RNG for signing */
&ptSigGiant.g);
break;
#endif /* RSA_PADDING_PKCS1_ENABLE */
default:
rtn = RSA_Unimplemented;
break;
}
if(rtn) {
rsaDebug1("RSA_Sign: AddPadding returned %s\n", rsaStatusStr(rtn));
goto errOut;
}
#if RSA_SIG_SHARE_GIANT
/*
* We init this. Not caller, not powermodCRT. But not before
* we're done with the signature buffer, which could be the same
* as dataToSign.
*/
localGiantAlloc(&signBuffer->g);
#endif /* RSA_SIG_SHARE_GIANT */
/* sig := (ptext ^ d) mod n */
showGiant("sign ptGiant", &ptSigGiant.g);
powermodCRT(&ptSigGiant.g,
&privKey->p.g, &privKey->pRecip.g,
&privKey->q.g, &privKey->qRecip.g,
&privKey->dp.g, &privKey->dq.g,
&privKey->qInv.g,
#if RSA_SIG_SHARE_GIANT
&signBuffer->g.g,
#else
&powermodScratch.g,
#endif
&ptSigGiant.g);
showGiant("sign sig ", &ptSigGiant.g);
#if RSA_SIG_SHARE_GIANT
/* our sigLen is not IN/OUT, but the arg to serializeGiant is */
*sigLen = sizeof(signBuffer->signature);
grtn = serializeGiant(&ptSigGiant.g, signBuffer->signature, sigLen);
#else
grtn = serializeGiant(&ptSigGiant.g, sig, sigLen);
#endif /* RSA_SIG_SHARE_GIANT */
if(grtn) {
rtn = giantStatusToRSA(grtn);
rsaDebug1("RSA_Sign: serializeGiant returned %s\n", rsaStatusStr(rtn));
}
errOut:
clearGiant(&ptSigGiant.g);
return rtn;
}
#endif /* RSA_SIGN_ENABLE */
#if RSA_VERIFY_ENABLE
extern RSAStatus RSA_SigVerify(
RSAPubGiantKey *pubKey, /* public key */
RSAPadding padding, /* RP_None or RP_PKCS1 */
const gi_uint8 *signedData, /* signature over this data */
gi_uint16 signedDataLen, /* length of dataToSign */
const gi_uint8 *sig, /* signature */
gi_uint16 sigLen) /* length of signature */
{
RSAStatus rtn = RSA_Success;
lgiant ptSigGiant; /* plain and decrypted signature */
GIReturn grtn;
GI_CHECK_SP("RSA_SigVerify");
GI_LOG_SP("RSA_SigVerify top");
if((signedData == NULL) || (sig == NULL)) {
return RSA_ParamErr;
}
if(pubKey == NULL) {
return RSA_ParamErr;
}
localGiantAlloc(&ptSigGiant);
rsaEnsurePubRecip(pubKey);
/* signature --> giant */
grtn = deserializeGiant(&ptSigGiant.g, sig, sigLen);
if(grtn) {
rtn = giantStatusToRSA(grtn);
rsaDebug1("RSA_SigVerify: deserializeGiant (sig) returned %s\n",
rsaStatusStr(rtn));
return rtn;
}
/* decrytped sig := (sig ^ e) mod n */
/* powermodg allows base and result to reside in same giant */
GI_LOG_SP("calling powermodg");
showGiant("vfy ptGiant", &ptSigGiant.g);
powermodg(&ptSigGiant.g, &pubKey->e.g,
&pubKey->n.g, &pubKey->recip.g,
&ptSigGiant.g);
showGiant("vfy sig ", &ptSigGiant);
/* check and strip padding, verify data */
switch(padding) {
case RP_None:
rtn = rsaCheckNoPaddingForSigVfy(&ptSigGiant.g, signedData, signedDataLen);
break;
#if RSA_PADDING_PKCS1_ENABLE
case RP_PKCS1:
rtn = rsaCheckPkcs1PaddingForSigVfy(&ptSigGiant.g, signedData, signedDataLen);
break;
#endif /* RSA_PADDING_PKCS1_ENABLE */
default:
rtn = RSA_Unimplemented;
break;
}
if(rtn) {
rsaDebug1("RSA_SigVerify: CheckPadding returned %s\n", rsaStatusStr(rtn));
}
clearGiant(&ptSigGiant.g);
return rtn;
}
#endif /* RSA_VERIFY_ENABLE */
#if RSA_ENCRYPT_ENABLE
extern RSAStatus RSA_Encrypt(
RSAPubGiantKey *pubKey, /* public key */
RSAPadding padding, /* RP_None, RP_PKCS1, RP_OAEP */
RSARngCallback *rngCallback, /* required for RP_PKCS1, RP_OAEP */
const gi_uint8 *plainText,
gi_uint16 plainTextLen, /* length of plainText */
gi_uint8 *cipherText,
gi_uint16 *cipherTextLen) /* IN/OUT */
{
RSAStatus rtn = RSA_Success;
lgiant ptCtGiant;
GIReturn grtn;
gi_uint16 modSize;
if((plainText == NULL) || (cipherText == NULL) || (cipherTextLen == NULL)) {
return RSA_ParamErr;
}
if(pubKey == NULL) {
return RSA_ParamErr;
}
GI_CHECK_SP("RSA_Encrypt");
localGiantAlloc(&ptCtGiant);
rsaEnsurePubRecip(pubKey);
modSize = giantNumBytes(&pubKey->n.g);
switch(padding) {
case RP_None:
rtn = rsaAddNoPadding(plainText, plainTextLen, &ptCtGiant.g);
break;
#if RSA_PADDING_PKCS1_ENABLE
case RP_PKCS1:
rtn = rsaAddPkcs1Padding(plainText, plainTextLen,
modSize, RSA_PKCS1_PAD_ENCRYPT,
rngCallback,
&ptCtGiant.g);
break;
#endif /* RSA_PADDING_PKCS1_ENABLE */
/* OEAP goes here eventually */
default:
rtn = RSA_Unimplemented;
break;
}
if(rtn) {
rsaDebug1("RSA_Encrypt: AddPadding returned %s\n", rsaStatusStr(rtn));
goto errOut;
}
/* ctext := (ptext ^ e) mod n */
/* ptext and ctext can share the same giant */
powermodg(&ptCtGiant.g, &pubKey->e.g,
&pubKey->n.g, &pubKey->recip.g,
&ptCtGiant.g);
/* out to caller */
grtn = serializeGiant(&ptCtGiant.g, cipherText, cipherTextLen);
if(grtn) {
rtn = giantStatusToRSA(grtn);
rsaDebug1("RSA_Encrypt: serializeGiant returned %s\n", rsaStatusStr(rtn));
}
errOut:
clearGiant(&ptCtGiant.g);
return rtn;
}
#endif /* RSA_ENCRYPT_ENABLE */
#if RSA_DECRYPT_ENABLE
RSAStatus RSA_Decrypt(
RSAPrivGiantKey *privKey, /* private key */
RSAPadding padding, /* RP_None, RP_PKCS1, RP_OAEP */
const gi_uint8 *cipherText,
gi_uint16 cipherTextLen, /* length of cipherText */
gi_uint8 *plainText,
gi_uint16 *plainTextLen) /* IN/OUT */
{
RSAStatus rtn = RSA_Success;
lgiant ptCtGiant;
GIReturn grtn;
lgiant powermodScratch;
if((plainText == NULL) || (cipherText == NULL) || (plainTextLen == NULL) || (privKey == NULL)) {
return RSA_ParamErr;
}
GI_CHECK_SP("RSA_Decrypt");
localGiantAlloc(&ptCtGiant);
localGiantAlloc(&powermodScratch);
rsaEnsurePrivRecip(privKey);
/* ciphertext --> giant */
grtn = deserializeGiant(&ptCtGiant.g, cipherText, cipherTextLen);
if(grtn) {
rtn = giantStatusToRSA(grtn);
rsaDebug1("RSA_Decrypt: deserializeGiant (sig) returned %s\n",
rsaStatusStr(rtn));
goto errOut;
}
/* plaintext := (ciphertext ^ d) mod n */
powermodCRT(&ptCtGiant.g,
&privKey->p.g, &privKey->pRecip.g,
&privKey->q.g, &privKey->qRecip.g,
&privKey->dp.g, &privKey->dq.g,
&privKey->qInv.g,
&powermodScratch.g,
&ptCtGiant.g);
/* check and strip padding */
switch(padding) {
case RP_None:
rtn = rsaCheckNoPadding(&ptCtGiant.g, plainText, plainTextLen);
break;
#if RSA_PADDING_PKCS1_ENABLE
case RP_PKCS1:
rtn = rsaCheckPkcs1Padding(&ptCtGiant.g, RSA_PKCS1_PAD_ENCRYPT,
plainText, plainTextLen);
break;
#endif /* RSA_PADDING_PKCS1_ENABLE */
/* OAEP here */
default:
rtn = RSA_Unimplemented;
break;
}
if(rtn) {
rsaDebug1("RSA_Decrypt: CheckPadding returned %s\n", rsaStatusStr(rtn));
}
errOut:
clearGiant(&ptCtGiant.g);
return rtn;
}
#endif /* RSA_DECRYPT_ENABLE */
+187
View File
@@ -0,0 +1,187 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* libgRSA.h - public API for RSA library based on libGiants
*/
#ifndef _LIBGRSA_LIBRSA_H_
#define _LIBGRSA_LIBRSA_H_
#include <libgRSA/rsaTypes.h>
#include <libgRSA/rsaGiantKey.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* This file declares the main public functions in the libgRSA library.
* Keys for all of these functions are expressed in "RSAGiantKey" format,
* defined in rsaGiantKey.h. This is the native key format for this
* library. RSAGiantKeys can be obtained in one of two ways:
*
* -- from DER-encoded, PKCS1-style key blobs, using the interface in
* libgRSA_DER.h.
* -- from raw byte strings representing individual key components, using
* the interface in rsaRawKey.h.
*/
/*
* RSA_SIG_SHARE_GIANT, when true, is an optimization to reduce the stack
* requirements when performing an RSA_Sign operation. When true, caller
* allocates an RSASignBuffer union which contains both a sratch giant
* for use by lower level code and the buffer into which a signature
* will be written at the completion of RSA_Sign(). The input,
* dataToSign, can also be in this RSASignBuffer (i.e., dataToSign
* can equal RSASignBuffer.signature).
*/
#define RSA_SIG_SHARE_GIANT 0
#if RSA_SIG_SHARE_GIANT
typedef union {
lgiant g;
gi_uint8 signature[MAX_PRIME_SIZE_BYTES];
} RSASignBuffer;
#endif /* RSA_SIG_SHARE_GIANT */
/*
* Given a private key and data to sign, generate a digital signature.
*
* If the padding argument is RP_PKCS1, PKCS1 padding will be performed
* prior to signing. If this argument is RP_None, the incoming data
* will be signed "as is". (OAEP padding is not supported for signing.)
* Note when PKCS1 padding is performed, the maximum length of data that
* can be signed is RSAKey.nLen-11 where RSAKey.nLen is the length of
* the modulus.
*
* NOTE: using RP_None will not work if the first byte of dataToSign
* is zero; there is no way to verify leading zeroes as they got chopped
* off during the calculation.
*
* If you want a proper PKCS1 style signature, with DER encoding of the
* incoming data - and the data is a SHA1 digest - use RSA_EncodeDigest
* to format the data in an encoded DigestInfo struct before calling
* this routine.
*
* If RSA_SIG_SHARE_GIANT is zero, caller allocates sig, the output buffer,
* into which the signature will be written. This must be at least as large
* as the key's modulus. On input, *sigLen is the size of the available buffer.
* On output it's the size of the signature actually written to sig.
*
* If RSA_SIG_SHARE_GIANT is nonzero, caller allocates the signBuffer of
* type RSASignBuffer; the signature will be written into
* signBuffer->signature and *sigLen will equal the size of the
* signature actually written to signBuffer->signature.
*
* When memory usage is a critical issue, note that the input buffer
* (dataToSign) can be the same as the output buffer (sig, or
* signBuffer->signature, depending on RSA_SIG_SHARE_GIANT).
*
* Returns an RSAStatus as described in libgRSA.h.
*/
#if RSA_SIG_SHARE_GIANT
extern RSAStatus RSA_Sign(
RSAPrivGiantKey *privKey, /* private key */
RSAPadding padding, /* RP_None or RP_PKCS1 */
const gi_uint8 *dataToSign, /* signature over this data */
gi_uint16 dataToSignLen, /* length of dataToSign */
RSASignBuffer *signBuffer, /* signature RETURNED here */
gi_uint16 *sigLen); /* signature RETURNED here */
#else /* !RSA_SIG_SHARE_GIANT */
extern RSAStatus RSA_Sign(
RSAPrivGiantKey *privKey, /* private key */
RSAPadding padding, /* RP_None or RP_PKCS1 */
const gi_uint8 *dataToSign, /* signature over this data */
gi_uint16 dataToSignLen, /* length of dataToSign */
gi_uint8 *sig, /* signature, RETURNED */
gi_uint16 *sigLen); /* IN/OUT */
#endif /* RSA_SIG_SHARE_GIANT */
/*
* Given a public key, data which has been signed, and a signature,
* verify the signature.
*
* If the padding argument is RP_PKCS1, PKCS1 padding will be performed
* prior to verification. If this argument is RP_None, the incoming data
* will be verified "as is". (OAEP padding is not supported for verifying.)
* Note when PKCS1 padding is performed, the maximum length of data that
* can be signed and verified is RSAKey.nLen-11 where RSAKey.nLen is the
* length of the modulus.
*
* If you are verifying a proper PKCS1 style signature, with DER encoding
* of the incoming data - and the data is a SHA1 digest - use
* DEREncodeSHA1DigestInfo to format the data in an encoded DigestInfo
* struct before calling this routine.
*
* Returns an RSAStatus as described above.
*/
extern RSAStatus RSA_SigVerify(
RSAPubGiantKey *pubKey, /* public key */
RSAPadding padding, /* RP_None or RP_PKCS1 */
const gi_uint8 *signedData, /* signature over this data */
gi_uint16 signedDataLen, /* length of dataToSign */
const gi_uint8 *sig, /* signature */
gi_uint16 sigLen); /* length of signature */
/*
* Encrypt a block of plaintext with a public key.
* Resulting ciphertext is the same size as the key's modulus
* (RSAKey.nLen) and is allocated by the caller.
* The cipherTextLen argument, on input, specifies how much
* space is available for the ciphertext; on return, it
* is the actual number of ciphertext bytes written.
*
* When performing RP_PKCS1 or RP_OAEP padding, you must supply
* a callback to a pseudorandom number generator via the rngFcn
* argument.
*
* When memory usage is a critical issue, note that the input buffer
* (plainText) can be the same as the output buffer (cipherText).
*
* Returns an RSAStatus as described above.
*/
extern RSAStatus RSA_Encrypt(
RSAPubGiantKey *pubKey, /* public key */
RSAPadding padding, /* RP_None, RP_PKCS1, RP_OAEP */
RSARngCallback *rngCallback, /* required for RP_PKCS1, RP_OAEP */
const gi_uint8 *plainText,
gi_uint16 plainTextLen, /* length of plainText */
gi_uint8 *cipherText,
gi_uint16 *cipherTextLen); /* IN/OUT */
/*
* Decrypt a block of ciphertext with a private key. The
* ciphertext must be equal in length to the size of the
* key's modulus. The plaintext buffer is allocated by
* the caller' en entry, *plainTextLen is the size of the
* available plaintext buffer; on return, it is the number
* of plaintext bytes actually written.
*
* When memory usage is a critical issue, note that the input buffer
* (cipherText) can be the same as the output buffer (plainText).
*
* Returns an RSAStatus as described above.
*/
extern RSAStatus RSA_Decrypt(
RSAPrivGiantKey *privKey, /* private key */
RSAPadding padding, /* RP_None, RP_PKCS1, RP_OAEP */
const gi_uint8 *cipherText,
gi_uint16 cipherTextLen, /* length of cipherText */
gi_uint8 *plainText,
gi_uint16 *plainTextLen); /* IN/OUT */
#ifdef __cplusplus
}
#endif
#endif /* _LIBRSA_LIBRSA_H_ */
+440
View File
@@ -0,0 +1,440 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* libgRSA_DER.c - DER encoding/decoding routines
*/
#include <libgRSA/libgRSA_DER.h>
#include <libgRSA/libgRSA_priv.h>
#include <libgRSA/libgRSA_config.h>
#include <libGiants/giantPlatform.h>
#include <libGiants/giantExternal.h>
#include <libGiants/giantMod.h>
#include <libGiants/giantDebug.h>
#include <libDER/DER_Keys.h>
#include <libDER/asn1Types.h>
#ifndef RSA_PKCS1_KEY_ENABLE
#error Please define RSA_PKCS1_KEY_ENABLE.
#endif
#if RSA_PKCS1_KEY_ENABLE
#if RSA_PUB_KEY_ENABLE || RSA_PRIV_KEY_ENABLE
/* init an lgiant, fill it with incoming bytes */
static RSAStatus rsaSetGiant(
lgiant *g,
DERItem *item)
{
localGiantAlloc(g);
if(deserializeGiant(&g->g, item->data, item->length)) {
return RSA_BadKeyData;
}
return RSA_Success;
}
#endif /* RSA_PUB_KEY_ENABLE || RSA_PRIV_KEY_ENABLE */
/*
* Decode PKCS1 form keys into RSA{Pub,Priv}GiantKey.
*/
#if RSA_PUB_KEY_ENABLE
RSAStatus RSA_DecodePubKey(
const unsigned char *pkcs1Key,
gi_uint16 pkcs1KeyLen,
RSAPubGiantKey *pubKey) /* RETURNED */
{
DERReturn drtn;
DERItem keyItem = {(DERByte *)pkcs1Key, pkcs1KeyLen};
DERRSAPubKeyPKCS1 decodedKey;
RSAStatus rrtn;
GI_CHECK_SP("RSA_DecodePubKey");
Bzero(pubKey, sizeof(*pubKey));
drtn = DERParseSequence(&keyItem,
DERNumRSAPubKeyPKCS1ItemSpecs, DERRSAPubKeyPKCS1ItemSpecs,
&decodedKey, sizeof(decodedKey));
if(drtn) {
return RSA_BadKeyData;
}
/* make_recip called lazily when the key is actually used */
localGiantAlloc(&pubKey->recip);
rrtn = rsaSetGiant(&pubKey->n, &decodedKey.modulus);
if(rrtn) {
return rrtn;
}
return rsaSetGiant(&pubKey->e, &decodedKey.pubExponent);
}
RSAStatus RSA_DecodeApplePubKey(
const unsigned char *pkcs1Key,
gi_uint16 pkcs1KeyLen,
RSAPubGiantKey *pubKey) /* RETURNED */
{
DERReturn drtn;
DERItem keyItem = {(DERByte *)pkcs1Key, pkcs1KeyLen};
DERRSAPubKeyApple decodedKey;
RSAStatus rrtn;
Bzero(pubKey, sizeof(*pubKey));
drtn = DERParseSequence(&keyItem,
DERNumRSAPubKeyAppleItemSpecs, DERRSAPubKeyAppleItemSpecs,
&decodedKey, sizeof(decodedKey));
if(drtn) {
return RSA_BadKeyData;
}
rrtn = rsaSetGiant(&pubKey->e, &decodedKey.pubExponent);
if(rrtn) {
return rrtn;
}
rrtn = rsaSetGiant(&pubKey->n, &decodedKey.modulus);
if(rrtn) {
return rrtn;
}
rrtn = rsaSetGiant(&pubKey->recip, &decodedKey.reciprocal);
if(rrtn) {
return rrtn;
}
return RSA_Success;
}
#endif /* RSA_PUB_KEY_ENABLE */
#if RSA_PRIV_KEY_ENABLE
/* init an rsaSgiant, fill it with incoming bytes */
static RSAStatus rsaSetSGiant(
rsaSgiant *g,
DERItem *item)
{
localSmallGiantAlloc(g);
if(deserializeGiant(&g->g, item->data, item->length)) {
return RSA_BadKeyData;
}
return RSA_Success;
}
RSAStatus RSA_DecodePrivKey(
const unsigned char *pkcs1Key,
gi_uint16 pkcs1KeyLen,
RSAPrivGiantKey *privKey) /* RETURNED */
{
DERReturn drtn;
DERItem keyItem = {(DERByte *)pkcs1Key, pkcs1KeyLen};
DERRSAPrivKeyCRT decodedKey;
Bzero(privKey, sizeof(*privKey));
drtn = DERParseSequence(&keyItem,
DERNumRSAPrivKeyCRTItemSpecs, DERRSAPrivKeyCRTItemSpecs,
&decodedKey, sizeof(decodedKey));
if(drtn) {
return RSA_BadKeyData;
}
if(rsaSetSGiant(&privKey->p, &decodedKey.p)) {
return RSA_BadKeyData;
}
if(rsaSetSGiant(&privKey->q, &decodedKey.q)) {
return RSA_BadKeyData;
}
if(rsaSetSGiant(&privKey->dp, &decodedKey.dp)) {
return RSA_BadKeyData;
}
if(rsaSetSGiant(&privKey->dq, &decodedKey.dq)) {
return RSA_BadKeyData;
}
if(rsaSetSGiant(&privKey->qInv, &decodedKey.qInv)) {
return RSA_BadKeyData;
}
/* pRecip, qRecip evaluated lazily */
localSmallGiantAlloc(&privKey->pRecip);
localSmallGiantAlloc(&privKey->qRecip);
return RSA_Success;
}
RSAStatus RSA_DecodeKeyPair(
const unsigned char *pkcs1Key,
gi_uint16 pkcs1KeyLen,
RSAFullGiantKey *keyPair) /* RETURNED */
{
DERReturn drtn;
DERItem keyItem = {(DERByte *)pkcs1Key, pkcs1KeyLen};
DERRSAKeyPair decodedKey;
Bzero(keyPair, sizeof(*keyPair));
drtn = DERParseSequence(&keyItem,
DERNumRSAKeyPairItemSpecs, DERRSAKeyPairItemSpecs,
&decodedKey, sizeof(decodedKey));
if(drtn) {
return RSA_BadKeyData;
}
if(rsaSetGiant(&keyPair->pub.n, &decodedKey.n)) {
return RSA_BadKeyData;
}
if(rsaSetGiant(&keyPair->pub.e, &decodedKey.e)) {
return RSA_BadKeyData;
}
if(rsaSetGiant(&keyPair->d, &decodedKey.d)) {
return RSA_BadKeyData;
}
if(rsaSetSGiant(&keyPair->priv.p, &decodedKey.p)) {
return RSA_BadKeyData;
}
if(rsaSetSGiant(&keyPair->priv.q, &decodedKey.q)) {
return RSA_BadKeyData;
}
if(rsaSetSGiant(&keyPair->priv.dp, &decodedKey.dp)) {
return RSA_BadKeyData;
}
if(rsaSetSGiant(&keyPair->priv.dq, &decodedKey.dq)) {
return RSA_BadKeyData;
}
if(rsaSetSGiant(&keyPair->priv.qInv, &decodedKey.qInv)) {
return RSA_BadKeyData;
}
/* recip, pRecip, qRecip evaluated lazily */
localGiantAlloc(&keyPair->pub.recip);
localSmallGiantAlloc(&keyPair->priv.pRecip);
localSmallGiantAlloc(&keyPair->priv.qRecip);
return RSA_Success;
}
#endif /* RSA_PRIV_KEY_ENABLE */
#if RSA_KEY_GENERATE_ENABLE
#define RSA_MAX_GIANT_SIZE MAX_SERIALIZED_GIANT_SIZE(GIANT_LITTLE_DIGITS)
/*
* Munge a giant (from e.g. a RSAFullGiantKey) into a gi_uint8 array
* and then into a DERItem suitable for encoding.
*/
static RSAStatus rsaGiantToDerItem(
giant g,
gi_uint8 *cp,
gi_uint16 cpLen,
DERItem *derItem)
{
GIReturn grtn;
gi_uint16 ioLen = cpLen;
gi_uint16 dex;
/* serialize the giant into DER content */
grtn = serializeGiant(g, cp, &ioLen);
if(grtn) {
return giantStatusToRSA(grtn);
}
/* convert the result into a DERItem */
derItem->data = cp;
derItem->length = ioLen;
/* trim off leading zeroes (but leave one zero if that's all there is) */
for(dex=0; dex<(ioLen-1); dex++) {
if(*(derItem->data) != 0) {
break;
}
derItem->data++;
derItem->length--;
}
return RSA_Success;
}
#if RSA_PUB_KEY_ENABLE
/* DER encode a public key, PKCS1 format */
RSAStatus RSA_EncodePubKey(
RSAPubGiantKey *giantKey,
gi_uint8 *pkcs1Key, /* data written here */
gi_uint32 *inOutLen) /* IN/OUT */
{
DERRSAPubKeyPKCS1 derKey;
DERReturn drtn;
RSAStatus rrtn;
DERByte *der = pkcs1Key;
DERSize ioLen = *inOutLen;
/* serialized giant byte arrays */
gi_uint8 nChars[RSA_MAX_GIANT_SIZE];
gi_uint8 eChars[RSA_MAX_GIANT_SIZE];
/* giants --> DERItems */
rrtn = rsaGiantToDerItem(&giantKey->n.g, nChars, RSA_MAX_GIANT_SIZE,
&derKey.modulus);
if(rrtn) {
return rrtn;
}
rrtn = rsaGiantToDerItem(&giantKey->e.g, eChars, RSA_MAX_GIANT_SIZE,
&derKey.pubExponent);
if(rrtn) {
return rrtn;
}
/* encode */
drtn = DEREncodeSequence(ASN1_CONSTR_SEQUENCE,
&derKey,
DERNumRSAPubKeyPKCS1ItemSpecs, DERRSAPubKeyPKCS1ItemSpecs,
der,
&ioLen);
if(drtn) {
return derStatusToRSA(drtn);
}
/* success */
*inOutLen = ioLen;
return RSA_Success;
}
/* DER encode a public key, custom (to this library) format with reciprocal */
RSAStatus RSA_EncodeApplePubKey(
RSAPubGiantKey *giantKey,
gi_uint8 *pubKey, /* data written here */
gi_uint32 *inOutLen) /* IN/OUT */
{
DERRSAPubKeyApple derKey;
DERReturn drtn;
RSAStatus rrtn;
DERByte *der = pubKey;
DERSize ioLen = *inOutLen;
bgiant recip;
/* serialized giant byte arrays */
gi_uint8 nChars[RSA_MAX_GIANT_SIZE];
gi_uint8 rChars[RSA_MAX_GIANT_SIZE];
gi_uint8 eChars[RSA_MAX_GIANT_SIZE];
/* calculate the reciprocal */
localBigGiantAlloc(&recip);
make_recip(&giantKey->n.g, &recip.g);
/* giants --> DERItems */
rrtn = rsaGiantToDerItem(&giantKey->n.g, nChars, RSA_MAX_GIANT_SIZE,
&derKey.modulus);
if(rrtn) {
return rrtn;
}
rrtn = rsaGiantToDerItem(&recip.g, rChars, RSA_MAX_GIANT_SIZE,
&derKey.reciprocal);
if(rrtn) {
return rrtn;
}
rrtn = rsaGiantToDerItem(&giantKey->e.g, eChars, RSA_MAX_GIANT_SIZE,
&derKey.pubExponent);
if(rrtn) {
return rrtn;
}
/* encode */
drtn = DEREncodeSequence(ASN1_CONSTR_SEQUENCE,
&derKey,
DERNumRSAPubKeyAppleItemSpecs, DERRSAPubKeyAppleItemSpecs,
der,
&ioLen);
if(drtn) {
return derStatusToRSA(drtn);
}
/* success */
*inOutLen = ioLen;
return RSA_Success;
}
#endif /* RSA_PUB_KEY_ENABLE */
#if RSA_PRIV_KEY_ENABLE
/*
* Create a PKCS1-formattted private key given a RSAFullGiantKey.
* The inOutLen param contains the number of bytes available in
* *pkcs1Key on entry, adn contains the number of bytes actually
* written to *pkcs1Key on successful return.
*/
RSAStatus RSA_EncodeKeyPair(
RSAFullGiantKey *keyPair,
gi_uint8 *pkcs1Key, /* data written here */
gi_uint32 *inOutLen) /* IN/OUT */
{
DERRSAKeyPair derKey;
DERReturn drtn;
RSAStatus rrtn;
DERByte *der = pkcs1Key;
DERSize ioLen = *inOutLen;
DERByte version = 0;
/* serialized giant byte arrays */
gi_uint8 nChars[RSA_MAX_GIANT_SIZE];
gi_uint8 eChars[RSA_MAX_GIANT_SIZE];
gi_uint8 dChars[RSA_MAX_GIANT_SIZE];
gi_uint8 pChars[RSA_MAX_GIANT_SIZE];
gi_uint8 qChars[RSA_MAX_GIANT_SIZE];
gi_uint8 dpChars[RSA_MAX_GIANT_SIZE];
gi_uint8 dqChars[RSA_MAX_GIANT_SIZE];
gi_uint8 qInvChars[RSA_MAX_GIANT_SIZE];
derKey.version.data = &version;
derKey.version.length = 1;
/* giants --> DERItems */
rrtn = rsaGiantToDerItem(&keyPair->pub.n.g, nChars, RSA_MAX_GIANT_SIZE, &derKey.n);
if(rrtn) {
return rrtn;
}
rrtn = rsaGiantToDerItem(&keyPair->pub.e.g, eChars, RSA_MAX_GIANT_SIZE, &derKey.e);
if(rrtn) {
return rrtn;
}
rrtn = rsaGiantToDerItem(&keyPair->d.g, dChars, RSA_MAX_GIANT_SIZE, &derKey.d);
if(rrtn) {
return rrtn;
}
rrtn = rsaGiantToDerItem(&keyPair->priv.p.g, pChars, RSA_MAX_GIANT_SIZE, &derKey.p);
if(rrtn) {
return rrtn;
}
rrtn = rsaGiantToDerItem(&keyPair->priv.q.g, qChars, RSA_MAX_GIANT_SIZE, &derKey.q);
if(rrtn) {
return rrtn;
}
rrtn = rsaGiantToDerItem(&keyPair->priv.dp.g, dpChars, RSA_MAX_GIANT_SIZE, &derKey.dp);
if(rrtn) {
return rrtn;
}
rrtn = rsaGiantToDerItem(&keyPair->priv.dq.g, dqChars, RSA_MAX_GIANT_SIZE, &derKey.dq);
if(rrtn) {
return rrtn;
}
rrtn = rsaGiantToDerItem(&keyPair->priv.qInv.g, qInvChars, RSA_MAX_GIANT_SIZE, &derKey.qInv);
if(rrtn) {
return rrtn;
}
/* encode */
drtn = DEREncodeSequence(ASN1_CONSTR_SEQUENCE,
&derKey,
DERNumRSAKeyPairItemSpecs, DERRSAKeyPairItemSpecs,
der,
&ioLen);
if(drtn) {
return derStatusToRSA(drtn);
}
/* success */
*inOutLen = ioLen;
return RSA_Success;
}
#endif /* RSA_PRIV_KEY_ENABLE */
#endif /* RSA_KEY_GENERATE_ENABLE */
#endif /* RSA_PKCS1_KEY_ENABLE */
+120
View File
@@ -0,0 +1,120 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* libgRSA_DER.h - DER encoding/decoding routines
*/
#ifndef _LIBGRSA_LIBRSA_DER_H_
#define _LIBGRSA_LIBRSA_DER_H_
#include <libgRSA/libgRSA.h>
#include <libgRSA/libgRSA_config.h>
#include <libGiants/giantPlatform.h>
#include <libDER/DER_Encode.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Decode PKCS1 form keys into RSA{Pub,Priv}GiantKey.
*/
RSAStatus RSA_DecodePubKey(
const unsigned char *pkcs1Key,
gi_uint16 pkcs1KeyLen,
RSAPubGiantKey *pubKey); /* RETURNED */
RSAStatus RSA_DecodePrivKey(
const unsigned char *pkcs1Key,
gi_uint16 pkcs1KeyLen,
RSAPrivGiantKey *privKey); /* RETURNED */
RSAStatus RSA_DecodeKeyPair(
const unsigned char *pkcs1Key,
gi_uint16 pkcs1KeyLen,
RSAFullGiantKey *keyPair); /* RETURNED */
/*
* Decode an custom (to this library) public key with reciprocal.
*/
RSAStatus RSA_DecodeApplePubKey(
const unsigned char *aplePubKey,
gi_uint16 applePubKeyLen,
RSAPubGiantKey *pubKey); /* RETURNED */
/*
* Generated key pair encoding support.
*/
#define RSA_HALF_SIZE(keySizeInBytes) ((keySizeInBytes + 1) / 2)
/*
* To allocate space on the stack for encoded public and private keys,
* use these macros to determine the max size needed. They are conservative;
* they will almost certainly allocate more space than you really
* end up needing for the encoded keys.
*/
#define RSA_ENCODED_PRIV_KEY_SIZE(keySizeInBytes) \
DER_MAX_ENCODED_SIZE( \
DER_MAX_ENCODED_SIZE(1) + /* version */ \
DER_MAX_ENCODED_SIZE(keySizeInBytes) + /* n */ \
DER_MAX_ENCODED_SIZE(keySizeInBytes) + /* e */ \
DER_MAX_ENCODED_SIZE(keySizeInBytes) + /* d */ \
DER_MAX_ENCODED_SIZE(RSA_HALF_SIZE(keySizeInBytes)) + /* p */ \
DER_MAX_ENCODED_SIZE(RSA_HALF_SIZE(keySizeInBytes)) + /* q */ \
DER_MAX_ENCODED_SIZE(RSA_HALF_SIZE(keySizeInBytes)) + /* dp */ \
DER_MAX_ENCODED_SIZE(RSA_HALF_SIZE(keySizeInBytes)) + /* dq */ \
DER_MAX_ENCODED_SIZE(RSA_HALF_SIZE(keySizeInBytes))) /* qInv */
#define RSA_ENCODED_PUB_KEY_SIZE(keySizeInBytes) \
DER_MAX_ENCODED_SIZE( \
DER_MAX_ENCODED_SIZE(keySizeInBytes) + /* n */ \
DER_MAX_ENCODED_SIZE(keySizeInBytes)) /* e */
#define RSA_ENCODED_APPLE_PUB_KEY_SIZE(keySizeInBytes) \
DER_MAX_ENCODED_SIZE( \
DER_MAX_ENCODED_SIZE(keySizeInBytes) + /* n */ \
DER_MAX_ENCODED_SIZE(keySizeInBytes) + /* recip */ \
GIANT_BYTES_PER_DIGIT + /* recip: one extra digit */ \
DER_MAX_ENCODED_SIZE(keySizeInBytes)) /* e */
/*
* Create PKCS1-formatted public key given a RSAFullGiantKey.
* The inOutLen param contains the number of bytes available in
* *pkcs1Key on entry, adn contains the number of bytes actually
* written to *pkcs1Key on successful return.
*/
RSAStatus RSA_EncodePubKey(
RSAPubGiantKey *giantKey,
gi_uint8 *pkcs1Key, /* data written here */
gi_uint32 *inOutLen); /* IN/OUT */
/*
* Create a PKCS1-formattted private key given a RSAFullGiantKey.
* The inOutLen param contains the number of bytes available in
* *pkcs1Key on entry, adn contains the number of bytes actually
* written to *pkcs1Key on successful return.
*/
RSAStatus RSA_EncodeKeyPair(
RSAFullGiantKey *keyPair,
gi_uint8 *pkcs1Key, /* data written here */
gi_uint32 *inOutLen); /* IN/OUT */
/*
* Create a custom (to this library) DER-encoded public key including
* the reciprocal.
* The inOutLen param contains the number of bytes available in
* *pubKey on entry, adn contains the number of bytes actually
* written to *pkcs1Key on successful return.
*/
RSAStatus RSA_EncodeApplePubKey(
RSAPubGiantKey *giantKey,
gi_uint8 *pubKey, /* data written here */
gi_uint32 *inOutLen); /* IN/OUT */
#ifdef __cplusplus
}
#endif
#endif /* _LIBGRSA_LIBRSA_DER_H_ */
+48
View File
@@ -0,0 +1,48 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* libgRSA_config.h - #defines controlling what features are enabled in a
* given implementation of this library.
*
* Created Aug. 9 2005 by Doug Mitchell.
*/
#ifndef _LIBGRSA_LIBRSA_CONFIG_H_
#define _LIBGRSA_LIBRSA_CONFIG_H_
/* one flag for each basic RSA operation */
#define RSA_SIGN_ENABLE 1
#define RSA_VERIFY_ENABLE 1
#define RSA_ENCRYPT_ENABLE 1
#define RSA_DECRYPT_ENABLE 1
/* values inferred from above four flags - do not modify */
#define RSA_SIGVFY_ENABLE (RSA_SIGN_ENABLE || RSA_VERIFY_ENABLE)
#define RSA_ENCRDECR_ENABLE (RSA_ENCRYPT_ENABLE || RSA_DECRYPT_ENABLE)
#define RSA_PUB_KEY_ENABLE (RSA_VERIFY_ENABLE || RSA_ENCRYPT_ENABLE)
#define RSA_PRIV_KEY_ENABLE (RSA_SIGN_ENABLE || RSA_DECRYPT_ENABLE)
/*
* Enables DER encoding of DigestInfo for proper PKCS1 signatures
* This is always disabled if !RSA_SIGVFY_ENABLE.
*/
#if RSA_SIGVFY_ENABLE
#define RSA_DER_DIGEST_ENABLE 1 /* your platform's value here */
#else
#define RSA_DER_DIGEST_ENABLE 0 /* hard coded - do not change */
#endif
/* enable support for PKCS1 and OEAP padding */
#define RSA_PADDING_PKCS1_ENABLE 1
#define RSA_PADDING_OAEP_ENABLE 0 /* not supported yet */
/* enable support for PKCS1 format keys */
#define RSA_PKCS1_KEY_ENABLE 1
/* enable support for raw keys (rsaRawKey.[ch]) */
#define RSA_RAW_KEY_ENABLE 1
/* enable key pair generation */
#define RSA_KEY_GENERATE_ENABLE 1
#endif /* _LIBGRSA_LIBRSA_CONFIG_H_ */
+86
View File
@@ -0,0 +1,86 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* libgRSA_priv.c - private libRSA routines.
*
* Created Aug. 10 2005 by Doug Mitchell.
*/
#include <libgRSA/libgRSA_priv.h>
/* convert a libGiants GIReturn to our own RSAStatus */
RSAStatus giantStatusToRSA(GIReturn grtn)
{
switch(grtn) {
case GR_Success: return RSA_Success;
case GR_IllegalArg: return RSA_ParamErr;
case GR_Unimplemented: return RSA_Unimplemented;
case GR_Internal: return RSA_InternalError;
case GR_Overflow: return RSA_Overflow;
default: return RSA_OtherError;
}
}
/* convert a libDER DERReturn to our own RSAStatus */
RSAStatus derStatusToRSA(DERReturn drtn)
{
switch(drtn) {
case DR_Success: return RSA_Success;
case DR_ParamErr: return RSA_ParamErr;
case DR_BufOverflow: return RSA_Overflow;
case DR_Unimplemented: return RSA_Unimplemented;
default: return RSA_BadKeyFormat;
}
}
#ifndef NDEBUG
#include <libGiantsUtils/GIReturnString.h>
/* be sure to update the mirrored copy in libgRSAUtils when this changes */
const char *rsaStatusStr(RSAStatus rrtn)
{
static char unknownStr[100];
if(rrtn < RSA_RETURN_BASE) {
if(rrtn == RSA_Success) {
return "RSA_Success";
}
else {
/* libGiants error */
return GIReturnString((GIReturn)rrtn);
}
}
switch(rrtn) {
case RSA_BadKeyData:
return "RSA_BadKeyData";
case RSA_ParamErr:
return "RSA_ParamErr";
case RSA_IncompleteKey:
return "RSA_IncompleteKey";
case RSA_VerifyFail:
return "RSA_VerifyFail";
case RSA_BadSigFormat:
return "RSA_BadSigFormat";
case RSA_BadDataFormat:
return "RSA_BadDataFormat";
case RSA_BadKeyFormat:
return "RSA_BadKeyFormat";
case RSA_InternalError:
return "RSA_InternalError";
case RSA_Overflow:
return "RSA_Overflow";
case RSA_Unimplemented:
return "RSA_Unimplemented";
case RSA_IllegalKeySize:
return "RSA_IllegalKeySize";
case RSA_OtherError:
return "RSA_OtherError";
default:
sprintf(unknownStr, "Unknown (%d)", rrtn);
return unknownStr;
}
}
#endif /* NDEBUG */
+56
View File
@@ -0,0 +1,56 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* libgRSA_priv.h - private libRSA routines.
*
* Created Aug. 10 2005 by Doug Mitchell.
*/
#ifndef _LIBGRSA_RSA_PRIV_H_
#define _LIBGRSA_RSA_PRIV_H_
#include <libgRSA/libgRSA.h>
#include <libGiants/giantIntegers.h>
#include <libDER/libDER.h>
#ifdef __cplusplus
extern "C" {
#endif
/* make sure NDEBUG is #define for deployment build! */
#define NDEBUG
#ifdef NDEBUG
#define rsaDebug(s)
#define rsaDebug1(s, a)
#define rsaDebug2(s, a, b)
#define RSAASSERT(s)
#else /* !NDEBUG */
#include <stdio.h>
#include <assert.h>
#define rsaDebug(s) printf(s)
#define rsaDebug1(s, a) printf(s, a)
#define rsaDebug2(s, a, b) printf(s, a, b)
#define RSAASSERT(s) assert(s)
#endif /* !NDEBUG */
/* convert a libGiants GIReturn to our own RSAStatus */
extern RSAStatus giantStatusToRSA(GIReturn grtn);
/* convert a libDER DERReturn to our own RSAStatus */
extern RSAStatus derStatusToRSA(DERReturn drtn);
/* convert an RSAStatus to a string (disabled for NDEBUG builds) */
extern const char *rsaStatusStr(RSAStatus rrtn);
#ifdef __cplusplus
}
#endif
#endif /* _LIBGRSA_RSA_PRIV_H_ */
+38
View File
@@ -0,0 +1,38 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* rsaGiantKey.c
*
* Created Aug. 9 2005 by Doug Mitchell.
*/
#include <libgRSA/rsaGiantKey.h>
#include <libGiants/giantIntegers.h>
#include <libGiants/giantDebug.h>
/* call this after declaring a local lgiant and before using it */
void localSmallGiantAlloc(rsaSgiant *g)
{
initGiant(&g->g, RSA_SMALL_GIANT_DIGITS, g->_n_);
}
/* clear an RSA{Pub,Priv}GiantKey */
void rsaClearPubGKey(
RSAPubGiantKey *gKey)
{
Bzero(gKey, sizeof(*gKey));
}
void rsaClearPrivGKey(
RSAPrivGiantKey *gKey)
{
Bzero(gKey, sizeof(*gKey));
}
void rsaClearFullGiantKey(
RSAFullGiantKey *gKey)
{
Bzero(gKey, sizeof(*gKey));
}
+78
View File
@@ -0,0 +1,78 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* rsaGiantKey.h - internal format of RSA keys, constructors for them.
*/
#ifndef _LIBGRSA_RSA_GIANT_KEY_H_
#define _LIBGRSA_RSA_GIANT_KEY_H_
#include <libgRSA/libgRSA_config.h>
#include <libGiants/giantIntegers.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* A custom "small" giant used to represent some individual fields in a
* RSAFullGiantKey. These fields are typically half the size of the
* modulus. We use MAX_PRIME_SIZE/2 + 1 digits for these.
*/
#define RSA_SMALL_GIANT_DIGITS ((MAX_PRIME_SIZE_DIGITS + 3) / 2)
typedef struct {
giantStruct g;
giantDigit _n_[RSA_SMALL_GIANT_DIGITS];
} rsaSmallGiantStruct;
typedef rsaSmallGiantStruct rsaSgiant; /* for heap allocation */
/* call this after declaring a local lgiant and before using it */
extern void localSmallGiantAlloc(rsaSgiant *g);
/* RSA public key form native to this library */
typedef struct {
lgiant e; /* public exponent */
lgiant n; /* modulus */
lgiant recip; /* reciprocal of n */
} RSAPubGiantKey;
/* RSA private key form native to this library */
typedef struct {
rsaSgiant p;
rsaSgiant q;
rsaSgiant dp;
rsaSgiant dq;
rsaSgiant qInv;
/* reciprocals of p and q */
rsaSgiant pRecip;
rsaSgiant qRecip;
} RSAPrivGiantKey;
/*
* A full RSA key pair.
*/
typedef struct {
RSAPubGiantKey pub;
lgiant d; /* private exponent */
RSAPrivGiantKey priv;
} RSAFullGiantKey;
/* clear an RSA*GiantKey */
void rsaClearPubGKey(
RSAPubGiantKey *gKey);
void rsaClearPrivGKey(
RSAPrivGiantKey *gKey);
void rsaClearFullGiantKey(
RSAFullGiantKey *gKey);
#ifdef __cplusplus
}
#endif
#endif /* _LIBGRSA_RSA_GIANT_KEY_H_ */
+532
View File
@@ -0,0 +1,532 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* rsaPadding.c - PKCS1 and OAEP padding support.
*
* Created Aug. 10 2005 by Doug Mitchell.
*/
#include <libgRSA/rsaPadding.h>
#include <libgRSA/libgRSA_config.h>
#include <libgRSA/libgRSA_priv.h>
#include <libGiants/giantExternal.h>
#include <libGiants/giantDebug.h>
#include <AssertMacros.h>
/*
* RP_None padding routines - just check length and convert between
* byte array and giant
*/
RSAStatus rsaAddNoPadding(
const unsigned char *plainText,
gi_uint16 plainTextLen,
giant result) /* RETURNED */
{
GIReturn rtn = deserializeGiant(result, plainText, plainTextLen);
return giantStatusToRSA(rtn);
}
RSAStatus rsaCheckNoPadding(
giant decryptResult,
unsigned char *plainText, /* data RETURNED here */
gi_uint16 *plainTextLen) /* IN/OUT */
{
GIReturn rtn = serializeGiant(decryptResult,
(gi_uint8 *)plainText, plainTextLen);
return giantStatusToRSA(rtn);
}
#if RSA_VERIFY_ENABLE
/*
* Decrement digit ptr and byte index thru a giant's n[],
* going from m.s. byte to l.s. byte.
* -- n[0] is the l.s. digit of a giant
* -- (n[0] & 0xff) is the l.s. byte of that digit
*/
static inline void decrGiantPtrs(
giantDigit **digitPtr,
gi_uint8 *byteDex)
{
if(*byteDex == 0) {
/* roll to m.s. byte of next l.s. digit */
(*digitPtr)--;
*byteDex = GIANT_BYTES_PER_DIGIT - 1;
}
else {
(*byteDex)--;
}
}
/* fetch specified byte from giant's n[] array */
static inline gi_uint8 getGiantByte(
giantDigit *digitPtr,
gi_uint8 byteDex)
{
giantDigit digit = *digitPtr;
digit >>= (byteDex * 8);
return (gi_uint8)digit;
}
/*
* How many bytes are left between current digit/byte markers and
* the start of the giant's data?
*/
static inline gi_size bytesLeftInGiant(
giant g,
giantDigit *digitPtr,
gi_uint8 byteDex)
{
GIASSERT(digitPtr >= g->n);
return ((digitPtr - g->n) * GIANT_BYTES_PER_DIGIT) + byteDex + 1;
}
/*
* Specialized "no padding" check for signature verify operation.
* We don't deserialize the decrypted giant; we do a byte-for-
* byte compare of the expected decrypted value against memory
* passed in to us, in-place in the decrypted giant.
* This saves two stack-allocated byte arrays, each of
* MAX_PRIME_SIZE_BYTES - one here, and one in RSA_SigVerify().
*
* NOTE: using "no padding" option will not work if the first byte
* (the m.s. byte of the decryptResult giant) is zero; there is
* no way to verify leading zeroes as they got chopped off during
* the calculation.
*/
RSAStatus rsaCheckNoPaddingForSigVfy(
giant decryptResult,
const unsigned char *expectPlainText,
gi_uint16 expectPlainTextLen)
{
unsigned dex;
giantDigit *digitPtr;
gi_uint8 byteDex;
gi_uint8 giantByte;
gi_size bytesLeft;
if((expectPlainText == NULL) || (decryptResult == NULL)) {
return RSA_InternalError;
}
if(expectPlainTextLen > MAX_PRIME_SIZE_BYTES) {
return RSA_Overflow;
}
if(decryptResult->sign == 0) {
if(expectPlainTextLen == 0) {
/* Well OK */
return RSA_Success;
}
else {
rsaDebug("rsaCheckNoPaddingForSigVfy: empty decryptResult\n");
return RSA_VerifyFail;
}
}
/*
* Prepare for scanning thru giant data, starting at the m.s. byte of the
* m.s. digit.
*/
digitPtr = &decryptResult->n[decryptResult->sign - 1];
byteDex = GIANT_BYTES_PER_DIGIT - 1;
bytesLeft = bytesLeftInGiant(decryptResult, digitPtr, byteDex);
GIASSERT(bytesLeft != 0);
/* find first non-zero byte */
for(;;) {
giantByte = getGiantByte(digitPtr, byteDex);
if(giantByte != 0) {
break;
}
decrGiantPtrs(&digitPtr, &byteDex);
if(--bytesLeft == 0) {
rsaDebug("rsaCheckNoPaddingForSigVfy: non nonzero data found\n");
return RSA_VerifyFail;
}
}
if(bytesLeft != expectPlainTextLen) {
rsaDebug("rsaCheckNoPaddingForSigVfy: length mismatch\n");
return RSA_VerifyFail;
}
for(dex=0; dex<bytesLeft; dex++) {
giantByte = getGiantByte(digitPtr, byteDex);
decrGiantPtrs(&digitPtr, &byteDex);
if(giantByte != expectPlainText[dex]) {
rsaDebug("rsaCheckNoPaddingForSigVfy: data miscompare\n");
return RSA_VerifyFail;
}
}
/* TA DA */
return RSA_Success;
}
#endif /* RSA_VERIFY_ENABLE */
#if RSA_PADDING_PKCS1_ENABLE
#define PKCS1_MIN_PAD_LEN 11 /* minumum length of padding */
#if RSA_SIGN_ENABLE || RSA_ENCRYPT_ENABLE
/* Write randSize bytes of nonzero data into randBuf. */
static RSAStatus nonZeroRandom(
RSARngCallback *rngCallback,
gi_uint8 *randBuf, /* random data goes here */
gi_uint16 randSize) /* byte count */
{
RSAStatus rstatus = RSA_Success;
gi_uint8 scratch[randSize];
gi_uint16 dix, six = randSize;
for (dix = 0; dix < randSize; ++dix) {
for (;;) {
if (six >= randSize) {
require_noerr(rstatus = rngCallback(scratch, randSize), errOut);
six = 0;
}
gi_uint8 b = scratch[six++];
if (b) {
randBuf[dix] = b;
break;
}
}
}
errOut:
/* Clear out scratch cause we like being paranoid. */
Bzero(scratch, randSize);
return rstatus;
}
/*
* Given plaintext or data to be signed, add PKCS1 padding and place
* the result in a giant.
*/
RSAStatus rsaAddPkcs1Padding(
const unsigned char *plainText,
gi_uint16 plainTextLen,
gi_uint16 totalLength, /* intended total length */
unsigned char padMarker, /* RSA_PKCS1_PAD_{SIGN,ENCRYPT} */
RSARngCallback *rngCallback, /* required for RP_PKCS1, RP_OAEP */
giant result)
{
unsigned char giantBytes[MAX_PRIME_SIZE_BYTES];
unsigned char *cp = giantBytes;
unsigned dex;
GIReturn grtn;
RSAStatus rrtn = RSA_Success;
unsigned psLen; /* length of variable length padding string */
if((plainText == NULL) || (result == NULL)) {
return RSA_InternalError;
}
if(totalLength > MAX_PRIME_SIZE_BYTES) {
return RSA_Overflow;
}
if(plainTextLen > (totalLength - PKCS1_MIN_PAD_LEN)) {
rsaDebug("rsaAddPkcs1Padding: insuffient space for padding\n");
return RSA_Overflow;
}
if((padMarker == RSA_PKCS1_PAD_ENCRYPT) && (rngCallback == NULL)) {
rsaDebug("rsaAddPkcs1Padding: RNG required\n");
return RSA_ParamErr;
}
*cp++ = 0;
*cp++ = padMarker;
/*
* RSA_PKCS1_PAD_SIGN: pad with 0xff
* RSA_PKCS1_PAD_ENCRYPT: pad with random nonzero data
*/
psLen = totalLength - plainTextLen - 3;
if(padMarker == RSA_PKCS1_PAD_ENCRYPT) {
/* Fill cp with psLen random nonzero bytes. */
rrtn = nonZeroRandom(rngCallback, cp, psLen);
if (rrtn) {
rsaDebug1("rsaAddPkcs1Padding: nonZeroRandom returned: %s\n",
rsaStatusStr(rrtn));
return rrtn;
}
cp += psLen;
} else {
for(dex=0; dex<psLen; dex++) {
*cp++ = 0xff;
}
}
*cp++ = 0;
Memcpy(cp, plainText, plainTextLen);
RSAASSERT((cp + plainTextLen) == (giantBytes + totalLength));
grtn = deserializeGiant(result, giantBytes, totalLength);
if(grtn) {
rrtn = giantStatusToRSA(grtn);
rsaDebug1("rsaAddPkcs1Padding: deserializeGiant returned %s\n",
rsaStatusStr(rrtn));
}
return rrtn;
}
#endif /* RSA_SIGN_ENABLE || RSA_ENCRYPT_ENABLE */
#if RSA_DECRYPT_ENABLE
/*
* Given decrypted plaintext in the form of a giant, which should
* be the same size as n, verify proper PKCS1 padding and copy
* resulting plaintext and length into caller-supplied buffer.
* ON entry, *plainTextLen indicates the size of the available
* plaintext buffer. ON return, *plainTextLen indicates the
* number of valid plaintext recovered.
*
* FIXME don't need padMarker any more...
*/
RSAStatus rsaCheckPkcs1Padding(
giant decryptResult,
unsigned char padMarker, /* RSA_PKCS1_PAD_{SIGN,ENCRYPT} */
unsigned char *plainText, /* data RETURNED here */
gi_uint16 *plainTextLen) /* IN/OUT */
{
unsigned char giantBytes[MAX_PRIME_SIZE_BYTES];
gi_uint16 giantBytesLen = MAX_PRIME_SIZE_BYTES;
unsigned char *cp = giantBytes;
GIReturn grtn;
RSAStatus rrtn = RSA_Success;
RSAStatus formatRtn;
unsigned char *giantEnd;
gi_uint16 validData;
unsigned dex;
if(padMarker == RSA_PKCS1_PAD_SIGN) {
formatRtn = RSA_BadSigFormat;
}
else {
formatRtn = RSA_BadDataFormat;
}
if((plainText == NULL) || (decryptResult == NULL)) {
return RSA_InternalError;
}
if(*plainTextLen < (MAX_PRIME_SIZE_BYTES - PKCS1_MIN_PAD_LEN)) {
return RSA_Overflow;
}
grtn = serializeGiant(decryptResult, giantBytes, &giantBytesLen);
if(grtn) {
rrtn = giantStatusToRSA(grtn);
rsaDebug1("rsaCheckPkcs1Padding: serializeGiant returned %s\n",
rsaStatusStr(rrtn));
return rrtn;
}
/*
* Leading zeroes are optional:
*
* 1. If the key's modulus size is not aligned to a giantDigit and the m.s.
* byte of decryptResult - which was set to zero when the padding was
* created - is the only byte in the m.s. giantDigit, OR giantDigit is
* one byte, then the leading zero will not appear in the serialized
* giantBytes.
* 2. If the key's modulus size is not aligned to a giantDigit, and the
* m.s. byte of decryptResult is neither the l.s. or the m.s. byte
* of the m.s. giantDigit, then we'll see extra zeroes at the m.s.
* end of the serialized giantBytes.
*/
for(dex=0; dex<GIANT_BYTES_PER_DIGIT-1; dex++) {
if(*cp != 0) {
break;
}
cp++;
}
if(*cp++ != padMarker) {
rsaDebug("rsaCheckPkcs1Padding: bad padMarker\n");
rrtn = formatRtn;
goto errOut;
}
/*
* RSA_PKCS1_PAD_SIGN: pad with 0xff
* RSA_PKCS1_PAD_ENCRYPT: pad with random nonzero data
*/
/* mark end of valid decrypted data */
giantEnd = giantBytes + giantBytesLen;
do {
unsigned char b = *cp++;
if(b == 0) {
/* normal termination */
break;
}
if(padMarker == RSA_PKCS1_PAD_SIGN) {
/* verify in this case else skip */
if(b != 0xff) {
rsaDebug("rsaCheckPkcs1Padding: SIGN pad\n");
rrtn = formatRtn;
goto errOut;
}
}
} while (cp < giantEnd);
validData = giantEnd - cp;
*plainTextLen = validData;
if(validData != 0) {
Memcpy(plainText, cp, validData);
}
errOut:
Bzero(giantBytes, MAX_PRIME_SIZE_BYTES);
return rrtn;
}
#endif /* RSA_DECRYPT_ENABLE */
#endif /* RSA_PADDING_PKCS1_ENABLE */
#if RSA_PADDING_PKCS1_ENABLE && RSA_VERIFY_ENABLE
/*
* Specialized PKCS1 padding check for signature verify operation.
* We don't deserialize the decrypted giant; we check for padding
* in place (in the decrypted giant's n[]), AND we do a byte-for-
* byte compare of the expected decrypted value against memory
* passed in to us. This saves two stack-allocated byte arrays,
* each of MAX_PRIME_SIZE_BYTES - one here, and one in RSA_SigVerify().
*
* Returns:
* -- RSA_Success, padding good and result compares OK
* -- RSA_VerifyFail, padding good but data miscompare
* -- RSA_BadSigFormat, bad padding
* -- RSA_Overflow, expectPlainText too big for this key with PKCS1 padding
* -- else usual gross errors
*/
RSAStatus rsaCheckPkcs1PaddingForSigVfy(
giant decryptResult,
const unsigned char *expectPlainText,
gi_uint16 expectPlainTextLen)
{
unsigned dex;
giantDigit *digitPtr;
gi_uint8 byteDex;
gi_uint8 giantByte;
gi_size bytesLeft;
gi_size numFFs = 0;
if((expectPlainText == NULL) || (decryptResult == NULL)) {
return RSA_InternalError;
}
if(expectPlainTextLen > (MAX_PRIME_SIZE_BYTES - PKCS1_MIN_PAD_LEN)) {
return RSA_Overflow;
}
GI_CHECK_SP("rsaCheckPkcs1PaddingForSigVfy");
/*
* Prepare for scanning thru giant data, starting at the m.s. byte of the
* m.s. digit.
*/
digitPtr = &decryptResult->n[decryptResult->sign - 1];
byteDex = GIANT_BYTES_PER_DIGIT - 1;
/*
* Padding of the pre-encrypted data is like so:
*
* one byte zero
* one byte pad marker (RSA_PKCS1_PAD_SIGN)
* 8 bytes of 0xff
* one byte of zero
* then the to-be-encrypted data
*
* Leading zeroes are optional:
*
* 1. If:
* -- The key's modulus size is not aligned to a giantDigit, AND
* -- the m.s. byte of decryptResult - which was set to zero when
* the padding was created - is the only byte in the m.s.
* giantDigit (i.e., num_bytes_of_decrypted_data mod
* sizeof(giantDigit) equals one,
* OR
* -- sizeof(giantDigit) == 1 byte
*
* THEN the leading zero will not appear in decryptResult.
*
* 2. If:
* -- The key's modulus size is not aligned to a giantDigit, AND
* -- The m.s. byte of decryptResult is neither the l.s. or the
* m.s. byte of the m.s. giantDigit,
*
* THEN then we'll see extra zeroes at the m.s. digit in decryptResult.
*/
for(;;) {
giantByte = getGiantByte(digitPtr, byteDex);
if(giantByte != 0) {
break;
}
decrGiantPtrs(&digitPtr, &byteDex);
if(digitPtr == decryptResult->n) {
/*
* rolled back to first digit, not enough for 11 bytes of
* padding.
* FIXME rewrite this when sizeof(giantDigit) > 11. :-)
*/
rsaDebug("rsaCheckPkcs1PaddingForSigVfy: no padMarker\n");
return RSA_BadSigFormat;
}
}
/* we're at the first nonzero byte */
if(giantByte != RSA_PKCS1_PAD_SIGN) {
rsaDebug("rsaCheckPkcs1PaddingForSigVfy: bad padMarker\n");
return RSA_BadSigFormat;
}
decrGiantPtrs(&digitPtr, &byteDex);
bytesLeft = bytesLeftInGiant(decryptResult, digitPtr, byteDex);
if(bytesLeft < 9) {
rsaDebug("rsaCheckPkcs1PaddingForSigVfy: no space left for padding\n");
return RSA_BadSigFormat;
}
/*
* Now skip over 0xff bytes and then one byte of zero.
*/
do {
giantByte = getGiantByte(digitPtr, byteDex);
decrGiantPtrs(&digitPtr, &byteDex);
bytesLeft--;
if(giantByte == 0xff) {
numFFs++;
continue;
}
else if(giantByte == 0) {
if(numFFs < 8) {
rsaDebug("rsaCheckPkcs1PaddingForSigVfy: insufficient padding\n");
return RSA_BadSigFormat;
}
/* start of decrypted data */
break;
}
else {
rsaDebug("rsaCheckPkcs1PaddingForSigVfy: bad padding (not ff)\n");
return RSA_BadSigFormat;
}
} while(bytesLeft != 0);
/* We're at the first decrypted data; compare with caller's expected data */
if(bytesLeft != expectPlainTextLen) {
rsaDebug("rsaCheckPkcs1PaddingForSigVfy: length mismatch\n");
return RSA_VerifyFail;
}
for(dex=0; dex<bytesLeft; dex++) {
giantByte = getGiantByte(digitPtr, byteDex);
decrGiantPtrs(&digitPtr, &byteDex);
if(giantByte != expectPlainText[dex]) {
rsaDebug("rsaCheckPkcs1PaddingForSigVfy: data miscompare\n");
return RSA_VerifyFail;
}
}
/* TA DA */
return RSA_Success;
}
#endif /* RSA_PADDING_PKCS1_ENABLE && RSA_VERIFY_ENABLE */
+97
View File
@@ -0,0 +1,97 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* rsaPadding.h - PKCS1 and OAEP padding support.
*
* Created Aug. 10 2005 by Doug Mitchell.
*/
#ifndef _LIBGRSA_RSA_PADDING_H_
#define _LIBGRSA_RSA_PADDING_H_
#include <libgRSA/libgRSA.h>
#include <libGiants/giantIntegers.h>
#ifdef __cplusplus
extern "C" {
#endif
/* PKCS1 padding markers */
#define RSA_PKCS1_PAD_SIGN 0x01
#define RSA_PKCS1_PAD_ENCRYPT 0x02
/*
* RP_None padding routines - just check length and convert between
* byte array and giant
*/
RSAStatus rsaAddNoPadding(
const unsigned char *plainText,
gi_uint16 plainTextLen,
giant result); /* RETURNED */
RSAStatus rsaCheckNoPadding(
giant decryptResult,
unsigned char *plainText, /* data RETURNED here */
gi_uint16 *plainTextLen); /* IN/OUT */
/*
* Specialized "no padding" check for signature verify operation.
* We don't deserialize the decrypted giant; we do a byte-for-
* byte compare of the expected decrypted value against memory
* passed in to us, in-place in the decrypted giant.
* This saves two stack-allocated byte arrays, each of
* MAX_PRIME_SIZE_BYTES - one here, and one in RSA_SigVerify().
*/
RSAStatus rsaCheckNoPaddingForSigVfy(
giant decryptResult,
const unsigned char *expectPlainText,
gi_uint16 expectPlainTextLen);
RSAStatus rsaAddPkcs1Padding(
const unsigned char *plainText,
gi_uint16 plainTextLen,
gi_uint16 totalLength, /* intended total length */
unsigned char padMarker, /* RSA_PKCS1_PAD_{SIGN,ENCRYPT} */
RSARngCallback *rngCallback, /* required for RP_PKCS1, RP_OAEP */
giant result);
/*
* Given decrypted plaintext in the form of a giant, which should
* be the same size as n, verify proper PKCS1 padding and copy
* resulting plaintext and length into caller-supplied buffer.
* On entry, *plainTextLen indicates the size of the available
* plaintext buffer. On return, *plainTextLen indicates the
* number of valid bytes of plaintext recovered.
*/
RSAStatus rsaCheckPkcs1Padding(
giant decryptResult,
unsigned char padMarker, /* RSA_PKCS1_PAD_{SIGN,ENCRYPT} */
unsigned char *plainText, /* data RETURNED here */
gi_uint16 *plainTextLen); /* IN/OUT */
/*
* Specialized PKCS1 padding check for signature verify operation.
* We don't deserialize the decrypted giant; we check for padding
* in place (in the decrypted giant's n[]), AND we do a byte-for-
* byte compare of the expected decrypted value against memory
* passed in to us. This saves two stack-allocated byte arrays,
* each of MAX_PRIME_SIZE_BYTES - one here, and one in RSA_SigVerify().
*
* Returns:
* -- RSA_Success, padding good and result compares OK
* -- RSA_VerifyFail, padding good but data miscompare
* -- RSA_BadSigFormat, bad padding
* -- RSA_Overflow, expectPlainText too big for this key with PKCS1 padding
* -- else usual gross errors
*/
RSAStatus rsaCheckPkcs1PaddingForSigVfy(
giant decryptResult,
const unsigned char *expectPlainText,
gi_uint16 expectPlainTextLen);
#ifdef __cplusplus
}
#endif
#endif /* _LIBGRSA_RSA_PADDING_H_ */
+120
View File
@@ -0,0 +1,120 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* rsaRawKey.h - Typedefs and declarations for RSA keys in raw format
*
* Created Nov. 29 2005 by Doug Mitchell.
*/
#include <libgRSA/rsaRawKey.h>
#include <libGiants/giantExternal.h>
#include <libGiants/giantMod.h>
#include <libgRSA/libgRSA_config.h>
#ifndef RSA_RAW_KEY_ENABLE
#error Please define RSA_RAW_KEY_ENABLE.
#endif
#if RSA_RAW_KEY_ENABLE
#if RSA_PUB_KEY_ENABLE || RSA_PRIV_KEY_ENABLE
/* init an lgiant, fill it with incoming bytes */
static RSAStatus rsaSetGiant(
lgiant *g,
unsigned char *c,
gi_uint16 cLen)
{
localGiantAlloc(g);
if(deserializeGiant(&g->g, c, cLen)) {
return RSA_BadKeyData;
}
return RSA_Success;
}
#endif /* RSA_PUB_KEY_ENABLE || RSA_PRIV_KEY_ENABLE */
#if RSA_PUB_KEY_ENABLE
/* raw (n, e) in API form --> public RSAGiantKey */
RSAStatus rsaInitPubGKey(
const RSAPubKey *apiKey,
RSAPubGiantKey *pubKey)
{
if((apiKey == NULL) || (pubKey == NULL)) {
return RSA_ParamErr;
}
if((apiKey->e == NULL) || (apiKey->n == NULL)) {
return RSA_IncompleteKey;
}
if(rsaSetGiant(&pubKey->n, apiKey->n, apiKey->nLen)) {
return RSA_BadKeyData;
}
if(rsaSetGiant(&pubKey->e, apiKey->e, apiKey->eLen)) {
return RSA_BadKeyData;
}
localGiantAlloc(&pubKey->recip);
if(apiKey->recip) {
/* caller provided reciprocal */
if(deserializeGiant(&pubKey->recip.g, apiKey->recip, apiKey->recipLen)) {
return RSA_BadKeyData;
}
}
/* else make_recip called lazily when the key is actually used */
return RSA_Success;
}
#endif /* RSA_PUB_KEY_ENABLE */
#if RSA_PRIV_KEY_ENABLE
/* init an rsaSgiant, fill it with incoming bytes */
static RSAStatus rsaSetSGiant(
rsaSgiant *g,
unsigned char *c,
gi_uint16 cLen)
{
localSmallGiantAlloc(g);
if(deserializeGiant(&g->g, c, cLen)) {
return RSA_BadKeyData;
}
return RSA_Success;
}
/* raw (p, q, dp, dq, qInv) --> private RSAPrivCRTGiantKey */
RSAStatus rsaInitPrivGKey(
const RSAPrivKey *apiKey,
RSAPrivGiantKey *privKey)
{
if((apiKey == NULL) || (privKey == NULL)) {
return RSA_ParamErr;
}
if((apiKey->p == NULL) || (apiKey->q == NULL) || (apiKey->dp == NULL) ||
(apiKey->dq == NULL) || (apiKey->qInv == NULL)) {
return RSA_ParamErr;
}
if(rsaSetSGiant(&privKey->p, apiKey->p, apiKey->pLen)) {
return RSA_BadKeyData;
}
if(rsaSetSGiant(&privKey->q, apiKey->q, apiKey->qLen)) {
return RSA_BadKeyData;
}
if(rsaSetSGiant(&privKey->dp, apiKey->dp, apiKey->dpLen)) {
return RSA_BadKeyData;
}
if(rsaSetSGiant(&privKey->dq, apiKey->dq, apiKey->dqLen)) {
return RSA_BadKeyData;
}
if(rsaSetSGiant(&privKey->qInv, apiKey->qInv, apiKey->qInvLen)) {
return RSA_BadKeyData;
}
/* pRecip, qRecip evaluated lazily */
localSmallGiantAlloc(&privKey->pRecip);
localSmallGiantAlloc(&privKey->qRecip);
return RSA_Success;
}
#endif /* RSA_PRIV_KEY_ENABLE */
#endif /* RSA_RAW_KEY_ENABLE */
+72
View File
@@ -0,0 +1,72 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* rsaRawKey.h - Typedefs and declarations for RSA keys in raw format
*
* Created Nov. 29 2005 by Doug Mitchell.
*/
#ifndef _LIBGRSA_RSA_RAW_KEY_H_
#define _LIBGRSA_RSA_RAW_KEY_H_
#include <libgRSA/libgRSA.h>
#include <libgRSA/rsaGiantKey.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Generic forms of RSA keys, public and private forms.
* All fields are in raw, unformatted binary format, as a byte pointer
* and a length, with the most significant byte first.
*
* The recip field in RSAPubKey is optional; it's the reciprocal of
* the modulus n. Providing this field is an optimization; if it's not
* provided, it will be calculated on the fly at some runtime cost. The
* recip field is not sensitive; it can be distributed and stored with
* no more security concern than the modulus itself. Providing the recip
* field yields approximately 28% speedup on public key operations.
*
* See libgRSAUtils/rsaKeyGen.[ch] or Tools/rsaKeyTool for info
* on obtaining the reciprocal.
*/
typedef struct {
unsigned char *n; /* modulus */
gi_uint16 nLen;
unsigned char *recip; /* reciprocal of modulus */
gi_uint16 recipLen;
unsigned char *e; /* public exponent */
gi_uint16 eLen;
} RSAPubKey;
/* Private key, CRT form */
typedef struct {
unsigned char *p;
gi_uint16 pLen;
unsigned char *q;
gi_uint16 qLen;
unsigned char *dp;
gi_uint16 dpLen;
unsigned char *dq;
gi_uint16 dqLen;
unsigned char *qInv;
gi_uint16 qInvLen;
} RSAPrivKey;
/* raw (n, e) --> public RSAPubGiantKey */
RSAStatus rsaInitPubGKey(
const RSAPubKey *apiKey,
RSAPubGiantKey *pubKey);
/* raw (p, q, dp, dq, qInv) --> private RSAPrivGiantKey */
RSAStatus rsaInitPrivGKey(
const RSAPrivKey *apiKey,
RSAPrivGiantKey *privKey);
#ifdef __cplusplus
}
#endif
#endif /* _LIBGRSA_RSA_CORE_H_ */
+66
View File
@@ -0,0 +1,66 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* rsaTypes.h - typedefs for libgRSA
*
* Created Nov. 30 2005 by Doug Mitchell.
*/
#ifndef _LIBRSA_RSA_TYPES_H_
#define _LIBRSA_RSA_TYPES_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <libGiants/giantTypes.h>
/*
* Error returns from this library.
*/
typedef enum {
RSA_Success = 0,
RSA_BadKeyData = RSA_RETURN_BASE, /* bad raw key data */
RSA_ParamErr, /* parameter error */
RSA_IncompleteKey, /* one or more RSAKey fields missing */
RSA_VerifyFail, /* signature verification failed */
RSA_BadSigFormat, /* improperly formatted signature */
RSA_BadDataFormat, /* improperly formatted ciphertext */
RSA_BadKeyFormat, /* improperly formatted public key */
RSA_InternalError, /* internal error */
RSA_Overflow, /* insufficent buffer provided */
RSA_Unimplemented, /* unimplemented in this configuration */
RSA_IllegalKeySize, /* Unsupported key size */
RSA_OtherError
} RSAStatus;
/*
* Padding styles
*/
typedef enum {
RP_None = 0, /* no padding */
RP_PKCS1, /* PKCS1, for signing and encrypting */
RP_OAEP /* OAEP, for encrypting only */
} RSAPadding;
/*
* Random number callback function. The caller of RSA_Encrypt or
* RSA_GenKeyPair supplies pseudorandom data for OAEP or PKCS1 padding
* generation or for key generation, via this callback.
*
* The destination of the random data is *randBuf, which is memory owned
* and maintained by the caller of this function.
*
* This function should return nonzero if it failed to obtain the number of
* random bytes requested.
*/
typedef int (RSARngCallback)(
gi_uint8 *randBuf, /* random data goes here */
gi_uint16 randSize); /* byte count */
#ifdef __cplusplus
}
#endif
#endif /* _LIBRSA_RSA_TYPES_H_ */
+47
View File
@@ -0,0 +1,47 @@
# Copyright (C) 2007 Apple Inc. All rights reserved.
#
# This document is the property of Apple Inc.
# It is considered confidential and proprietary.
#
# This document may not be reproduced or transmitted in any form,
# in whole or in part, without the express written permission of
# Apple Inc.
#
LIBPKI_DIR := $(GET_LOCAL_DIR)
LIBPKI_BUILD := $(call TOLIBDIR,$(LIBPKI_DIR)/LIBPKI.a)
COMMONLIBS += LIBPKI
# Only process the remainder of the makefile if we are building libraries
#
ifeq ($(MAKEPHASE),libraries)
GLOBAL_INCLUDES += $(LIBPKI_DIR)
LIBPKI_OBJS := \
$(LIBPKI_DIR)/libDER/DER_CertCrl.o \
$(LIBPKI_DIR)/libDER/DER_Decode.o \
$(LIBPKI_DIR)/libDER/DER_Digest.o \
$(LIBPKI_DIR)/libDER/DER_Encode.o \
$(LIBPKI_DIR)/libDER/DER_Keys.o \
$(LIBPKI_DIR)/libDER/oids.o \
$(LIBPKI_DIR)/libGiants/giantExternal.o \
$(LIBPKI_DIR)/libGiants/giantIntegers.o \
$(LIBPKI_DIR)/libGiants/giantMemutils.o \
$(LIBPKI_DIR)/libGiants/giantPort_C.o \
$(LIBPKI_DIR)/libGiants/giantMod.o \
$(LIBPKI_DIR)/libgRSA/rsaGiantKey.o \
$(LIBPKI_DIR)/libgRSA/libgRSA.o \
$(LIBPKI_DIR)/libgRSA/rsaPadding.o \
$(LIBPKI_DIR)/libgRSA/libgRSA_priv.o \
$(LIBPKI_DIR)/libgRSA/libgRSA_DER.o \
$(LIBPKI_DIR)/libgRSA/rsaRawKey.o
LIBPKI_OBJS := $(call TOLIBOBJDIR,$(LIBPKI_OBJS))
$(LIBPKI_BUILD): $(LIBPKI_OBJS)
ALL_DEPS += $(LIBPKI_OBJS:%o=%d)
endif
+25
View File
@@ -0,0 +1,25 @@
# Copyright (C) 2007 Apple Inc. All rights reserved.
#
# This document is the property of Apple Inc.
# It is considered confidential and proprietary.
#
# This document may not be reproduced or transmitted in any form,
# in whole or in part, without the express written permission of
# Apple Inc.
#
LOCAL_DIR := $(GET_LOCAL_DIR)
OPTIONS += \
WITH_PKI=1 \
PKI_CHECK_ANCHOR_BY_SHA1=0 \
PKI_APPLE_ROOT_CA=1 \
PKI_CHECK_KEY_IDS=1
LIBRARY_MODULES += \
lib/pki
GLOBAL_INCLUDES += $(LOCAL_DIR)
ALL_OBJS += \
$(LOCAL_DIR)/debug.o \
$(LOCAL_DIR)/chain-validation.o
@@ -0,0 +1,86 @@
Getting set up with the fake hierarchy:
Modify lib/pki/rules.mk: set PKI_APPLE_ROOT_CA=0 to switch to the fake hierarchy and build a debug app test, ie. iBSS.
Load the various images
Get the keys and certs and CSRs from lib/pki/fake_ca.h for the intermediate: intermediate-cert.pem intermediate-key.pem, put them into separate .pem files.
Convert intermediate-cert.pem to der using openssl x509 -in intermediate-cert.pem -outform der -out intermediate-cert.der.
The USB_SERIAL_NUMBER header contains the board specific info, you may need to modify.
Useful images to create:
Images that try to set the current settings. Production status, chip and security domain should never be set by image itself.
img-dev-sdom-chip --development --chipType 0x8720 --domain darwin
img-dev-sdom-chip-epoch --development --chipType 0x8720 --domain darwin --epoch 0
img-dev-sdom-chip-boardid --development --chipType 0x8720 --domain darwin --boardID 0
img-dev-sdom-chip-uniqueid --development --chipType 0x8720 --domain darwin --uniqueID 0x????
One image to make sure the production switch works as expected. Modify chipid_get_production_mode in platform/*/chipid/chipid.c to simulate a production unit.
img-prod-sdom-chip --production --chipType 0x8720 --domain darwin
One leaf for the current settings:
spec-dev-8720-darwin --development --chipType 0x8720 --domain darwin
Leafs that modifies one of the settings away from the default (always supposed to come from the cert)
spec-dev-8720-manu --development --chipType 0x8720 --domain manufacturer
spec-dev-8920-darwin --development --chipType 0x8920 --domain darwin
spec-prod-8720-darwin --production --chipType 0x8720 --domain darwin
Leafs that modify epoch, boardid or ecid, away from the default (okay for the image to specify if cert doesn't)
spec-dev-8720-darwin-wrong-epoch --development --chipType 0x8720 --domain darwin --epoch 1
spec-dev-8720-darwin-wrong-boardid --development --chipType 0x8720 --domain darwin --boardID 1
spec-dev-8720-darwin-wrong-ecid --development --chipType 0x8720 --domain darwin --uniqueID 0
Tests of image and leaf combinations:
spec-dev-8720-darwin img-dev-sdom-chip OK
spec-dev-8720-manu img-dev-sdom-chip FAIL
spec-dev-8920-darwin img-dev-sdom-chip FAIL
spec-prod-8720-darwin img-dev-sdom-chip OK
spec-prod-8720-darwin img-dev-sdom-chip OK * board set to return production
spec-dev-8720-darwin img-prod-sdom-chip FAIL * board set to return production
spec-dev-8720-darwin-wrong-epoch img-dev-sdom-chip-epoch FAIL
spec-dev-8720-darwin-wrong-boardid img-dev-sdom-chip-boardid FAIL
spec-dev-8720-darwin-wrong-ecid img-dev-sdom-chip-uniqueid FAIL (w/ 32 bit clipped ECID)
Make img3 specs and put them into the extensions.txt file used during signing:
make-img3-specs is a shell script that converts img3 blobs into spec extensions to be used when signing.
make-img3-specs > extensions.txt
Generating one key that will be shared for all issued leafs:
openssl req -newkey rsa:1024 -sha1 -days 365 -sha1 \
-subj "/C=US/O=Apple Inc./OU=Apple Secure Boot Certification Authority/CN=S5L8900 Secure Boot" \
-nodes -out leaf-csr.pem -keyout leaf-key.pem
(note: common name is not checked in leaf - platform is derived from embedded img3)
Sign all leafs:
for i in spec-dev-8720-darwin spec-dev-8720-manu spec-dev-8920-darwin spec-prod-8720-darwin \
spec-dev-8720-darwin-wrong-epoch spec-dev-8720-darwin-wrong-boardid spec-dev-8720-darwin-wrong-ecid;
do
openssl x509 -req -sha1 -in leaf-csr.pem -CA intermediate-cert.pem -CAkey intermediate-key.pem \
-set_serial 42 -outform der -out $i.der -extfile extensions.txt -extensions $i
done
Create and sign images:
to_binary_hash.c is an emergency hack for conversion from image3maker output.
The image is generated and signed in the first steps:
image3maker --create --imagefile iBSS.img3 --type ibot --data iBSS.bin <pass in tags for image here>
image3maker --hashForSigning --imagefile iBSS.img3 | to_binary_hash > iBSS.hash
openssl rsautl -sign -inkey leaf-key.pem -in iBSS.hash -out iBSS.sig
It can be tested with various leafs (because all use the same key):
cat intermediate-cert.der spec-dev-8720-darwin.der > chain.der
image3maker --signWithData --signWithSignature iBSS.sig --signWithCertChain chain.der --imagefile iBSS.img3
Binary file not shown.
+27
View File
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAvcWxBbLPL3G9uKlfzEGg9bBBTm9T2Wzl3/GlkcWZwbaZlutT
Ir9ywzm454FSBgZd+bhsktYm3JJrJe29guj0FGN0x8AnBg0dzqBixGNNwA8YMPEn
SxCvbtHxL90QAyv+bggx1MD4eXbuPMpqn3hgHlLqbMVQsUj8RG95wkRjRfHbQutc
zqenlz69mxOUd1HY5LzLu+yu2Dm0FSPjwzCadPTZ3gPos8lBvHt5B2Ty/+6tXHhB
YHq4FofmJY0ADRoQrm4Ml8oHtu94Djh+UCtXyC8G36to/j5C+FTYB6cPY33hTTlc
+8OPBzijYp1h7lrcLvafpfWIZAXbTGg4ldxvMwIDAQABAoIBAQCvUe5DN3iVel0u
NrwcNh2AHb+XuN4cJrEQfWzbCVUNU6b9eJarqXdayP78Ucr3afZz+F/GIDZy3IpE
1iiYwqKMG34N9IWY35FEDYRxrtRrtQZCYOhOPzH0DdzmvTJH2+MIwGVZCpYDkU5z
twVeIpWaLjwJFRmBT85PYzV3tjqIqFnIzQhU8CRb52MFsyvTSpsycPAaLbnZ2wr2
KT9gOtCv61SKuTqPm2NhrYL34lJCHORySBe4Ts5vmjX75pBd00eDFTz6Fzwo9ePk
65nV3Vf7CKfqXLyV8ZHLU5xoMaPYvEY/mb1W1J+IsZ77juPAnQQ/aYqdUTDkjsq4
F5nJ3PlBAoGBAO5Z44eGsKclr1sVNo+QAchZqYSyyFKojKfnZHWztIfXdR9xZksg
zXSPQ0EbGdVK+ETDNZ4FWMCbllx69lLcnig8CN/6XKsKvjkw2mu0aS0I34RmozHo
mk2UV7KN3BLN8n7LSl1nucnI0mLFjZYpBQB/fnCS8F03TSDU97WEoupDAoGBAMvS
9LvcgfOUzIVD/MIJeYYxRJnroUcSijqs3Pp9ReWzRie9W7FOzM4gsSIs/wZh4dce
XIgS8mEobGTQH8dX5GostiKqJQq/E0Oa9i7QDmKOzVYqXjq+RuWu7GDmSb9kZ2g9
03GItxlwODNIAgpVT3p4FMDvTR+DsDdDF9jrMXBRAoGAFAOKPnQJ208nxU8nsLBX
5fnZaSIV/hLXFLYyUkvPqeRmmkhMXZyYg+QPsqTS630LEcMOeoFabXnjC0rr6hNK
WHiKCjyckWQqiuTWQlr4xeZL1nND2sn8Qu1k28Jbq1yNsyXgza0LBa2ONOr/s48o
M12BQXSlKD6fhFU9o4lKoL8CgYEAoH3XnyUeXkJIWJcUK2VyfyvELL7RGzmKBnGe
/s4tf5UOJLSBwredpKExWQu9M7VXMyABFFR27fH6h9cpbrnSbZgPQnRe/ns+G/mk
52+EJC71mGd8Ex1IjgqSriom38GbewVTvQ49vpYSaq7EjIZoMrLjBJhpTetPkfQO
jwuCvkECgYAqKEjuLbX+nhzQkd6pvz/69fTL1VyHZlvzS/ZDnSuJWQ1EgJDv39Q8
HLdFqzouNmfPU/dZiTPpOQTy2DYcRnFgwIhxKjrlSI8N3NtAjb5F78GixwfvsxVw
+jh3GPYgL9xXKDDgnaLdkhGNuHR2aEiAWpXlz5PURgSVMqR8tgKZnw==
-----END RSA PRIVATE KEY-----
+39
View File
@@ -0,0 +1,39 @@
#!/bin/zsh
function make-img3-spec()
{
TEMP_FILE=tmp$$
image3maker --create --imagefile "${TEMP_FILE}.img3" --type cert $*
if [ $? -ne 0 ]; then exit 1; fi
FILESIZE=$(wc -c < "${TEMP_FILE}.img3")
if [ ${FILESIZE} -gt 127 ];
then echo script too dumb to encode asn.1 length greater than 127
exit 1
fi
printf "1.2.840.113635.100.6.1.1=critical,DER:04:%02X" ${FILESIZE}
od -vt x1 "${TEMP_FILE}.img3" |\
sed -e 's/^[0-9a-f]*//g' -e 's/ *\([0-9a-f][0-9a-f]\)/:\1/g' |\
tr -d ' \n'
echo
rm ${TEMP_FILE}.img3
}
GENERAL_SPEC="keyUsage = digitalSignature
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always"
echo "[ spec-dev-8720-darwin ]"; echo ${GENERAL_SPEC}; echo $(make-img3-spec --development --chipType 0x8720 --domain darwin )
echo
echo "[ spec-dev-8720-manu ]"; echo ${GENERAL_SPEC}; echo $(make-img3-spec --development --chipType 0x8720 --domain manufacturer )
echo
echo "[ spec-dev-8920-darwin ]"; echo ${GENERAL_SPEC}; echo $(make-img3-spec --development --chipType 0x8920 --domain darwin )
echo
echo "[ spec-prod-8720-darwin ]"; echo ${GENERAL_SPEC}; echo $(make-img3-spec --production --chipType 0x8720 --domain darwin )
echo
echo "[ spec-dev-8720-darwin-wrong-epoch ]"; echo ${GENERAL_SPEC}; echo $(make-img3-spec --development --chipType 0x8720 --domain darwin --epoch 1)
echo
echo "[ spec-dev-8720-darwin-wrong-boardid ]"; echo ${GENERAL_SPEC}; echo $(make-img3-spec --development --chipType 0x8720 --domain darwin --boardID 1 )
echo
echo "[ spec-dev-8720-darwin-wrong-ecid ]"; echo ${GENERAL_SPEC}; echo $(make-img3-spec --development --chipType 0x8720 --domain darwin --uniqueID 0 )
echo
+43
View File
@@ -0,0 +1,43 @@
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// SHA1(iBSS.img3)= b51f78b42bb2d13281b4606b1446eb417625a657
unsigned char hex_to_bin(unsigned char hexchar)
{
unsigned char val = hexchar - '0';
if (val < 10)
return val;
val -= ('a' - '0' - 10);
if (val < 16)
return val;
return 255;
}
int main(int argc, char *argv[])
{
const unsigned char sha1oid[] = { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
const char prefix[] = "SHA1(", postfix[] = ")= ";
char data[80];
char *hash = fgets(data, sizeof(data), stdin);
if (0 == strncmp(prefix, hash, sizeof(prefix) - 1)) {
hash += sizeof(prefix) - 1; /* leave off null */
hash = strstr(hash, postfix);
if (!hash)
return -1;
hash += sizeof(postfix) - 1; /* leave off null */
int i;
for(i=0; i < sizeof(sha1oid); i++)
putc(sha1oid[i], stdout);
while (*hash && (*hash != '\n')) {
unsigned char value = hex_to_bin(*hash++) << 4 | hex_to_bin(*hash++);
putc(value, stdout);
}
}
}