first and last commit
This commit is contained in:
commit
1bf4efd552
2612 files changed
+636500
No files matched your search
@@ -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 */
|
||||
@@ -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
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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);
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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 */
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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_ */
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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_ */
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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_ */
|
||||
@@ -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 */
|
||||
@@ -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_ */
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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_ */
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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_ */
|
||||
@@ -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_*/
|
||||
@@ -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_ */
|
||||
@@ -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_ */
|
||||
@@ -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 */
|
||||
@@ -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_*/
|
||||
@@ -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_ */
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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_ */
|
||||
@@ -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 */
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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_ */
|
||||
@@ -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 */
|
||||
@@ -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_ */
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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 */
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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 */
|
||||
@@ -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_ */
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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
|
||||
@@ -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.
@@ -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-----
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user