1/* 2 * Copyright (c) 2005-2008,2010-2011,2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25/* 26 * DER_Digest.h - DER encode a DigestInfo 27 * 28 */ 29 30#include <libDER/DER_Digest.h> 31 32/* 33 * Create an encoded DigestInfo based on the specified SHA1 digest. 34 * The digest must be 20 bytes long. 35 * 36 * Result is placed in caller's buffer, which must be at least of 37 * length DER_DIGEST_INFO_LEN bytes. 38 * 39 * The *resultLen parameter is the available size in the result 40 * buffer on input, and the actual length of the encoded DigestInfo 41 * on output. 42 * 43 * In the interest of saving code space, this just drops the caller's 44 * digest into an otherwise hard-coded, fixed, encoded SHA1 DigestInfo. 45 * Nothing is variable so we know the whole thing. It looks like this: 46 * 47 * SEQUENCE OF <33> { 48 * SEQUENCE OF <9> { 49 * OID <5>: OID : < 06 05 2B 0E 03 02 1A > 50 * NULL 51 * } 52 * OCTET STRING <20>: 53 * 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 54 * 55 55 55 55 55 * } 56 * 57 * 58 * tower.local:digestInfo> hexdump -x /tmp/encodedDigest 59 * 0000000 3021 3009 0605 2b0e 0302 1a05 0004 1455 60 * 0000010 5555 5555 5555 5555 5555 5555 5555 5555 61 * * 62 * 0000020 63 */ 64 65static const unsigned char encodedSha1Digest[] = 66{ 67 0x30, 0x21, /* top level sequence length 33 */ 68 0x30, 0x09, /* algorithm ID, sequence length 9 */ 69 0x06, 0x05, /* alg OID, length 5, SHA1 */ 70 0x2b, 0x0e, 0x03, 0x02, 0x1a, 71 0x05, 0x00, /* NULL parameters */ 72 0x04, 0x14 /* integer length 20 */ 73 /* digest follows */ 74}; 75 76DERReturn DEREncodeSHA1DigestInfo( 77 const DERByte *sha1Digest, 78 DERSize sha1DigestLen, 79 DERByte *result, /* encoded result RETURNED here */ 80 DERSize *resultLen) /* IN/OUT */ 81{ 82 DERSize totalLen = sizeof(encodedSha1Digest) + DER_SHA1_DIGEST_LEN; 83 84 if((sha1Digest == NULL) || (sha1DigestLen != DER_SHA1_DIGEST_LEN) || 85 (result == NULL) || (resultLen == NULL)) { 86 return DR_ParamErr; 87 } 88 if(*resultLen < DER_SHA1_DIGEST_INFO_LEN) { 89 return DR_BufOverflow; 90 } 91 DERMemmove(result, encodedSha1Digest, sizeof(encodedSha1Digest)); 92 DERMemmove(result + sizeof(encodedSha1Digest), sha1Digest, DER_SHA1_DIGEST_LEN); 93 *resultLen = totalLen; 94 return DR_Success; 95} 96 97/* 98 joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) 99 csor(3) nistalgorithm(4) hashAlgs(2) sha256(1) 100 101 future ones to add: sha384(2) sha512(3) sha224(4) 102*/ 103static const unsigned char encodedSha256Digest[] = 104{ 105 0x30, 0x31, /* top level sequence length 49 */ 106 0x30, 0x0d, /* algorithm ID, sequence length 13 */ 107 0x06, 0x09, 108 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 109 0x05, 0x00, /* NULL parameters */ 110 0x04, 0x20 /* integer length 32 */ 111 /* digest follows */ 112}; 113 114DERReturn DEREncodeSHA256DigestInfo( 115 const DERByte *sha256Digest, 116 DERSize sha256DigestLen, 117 DERByte *result, /* encoded result RETURNED here */ 118 DERSize *resultLen) /* IN/OUT */ 119{ 120 DERSize totalLen = sizeof(encodedSha256Digest) + DER_SHA256_DIGEST_LEN; 121 122 if((sha256Digest == NULL) || (sha256DigestLen != DER_SHA256_DIGEST_LEN) || 123 (result == NULL) || (resultLen == NULL)) { 124 return DR_ParamErr; 125 } 126 if(*resultLen < DER_SHA256_DIGEST_INFO_LEN) { 127 return DR_BufOverflow; 128 } 129 DERMemmove(result, encodedSha256Digest, sizeof(encodedSha256Digest)); 130 DERMemmove(result + sizeof(encodedSha256Digest), sha256Digest, DER_SHA256_DIGEST_LEN); 131 *resultLen = totalLen; 132 return DR_Success; 133} 134 135 136/* Same thing, MD5/MD2 */ 137static const unsigned char encodedMdDigest[] = 138{ 139 0x30, 0x20, /* top level sequence length 32 */ 140 0x30, 0x0c, /* algorithm ID, sequence length 12 */ 141 0x06, 0x08, /* alg OID, length 8, MD2/MD5 */ 142 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 143 0x05, /* 5 = MD5, 2 = MD2 */ 144 0x05, 0x00, /* NULL parameters */ 145 0x04, 0x10 /* integer length 16 */ 146 /* digest follows */ 147}; 148 149#define WHICH_DIGEST_INDEX 13 150#define WHICH_DIGEST_MD2 2 151#define WHICH_DIGEST_MD5 5 152 153DERReturn DEREncodeMDDigestInfo( 154 WhichDigest whichDigest, 155 const DERByte *mdDigest, 156 DERSize mdDigestLen, 157 DERByte *result, /* encoded result RETURNED here */ 158 DERSize *resultLen) /* IN/OUT */ 159{ 160 DERSize totalLen = sizeof(encodedMdDigest) + DER_MD_DIGEST_LEN; 161 162 if((mdDigest == NULL) || (mdDigestLen != DER_MD_DIGEST_LEN) || 163 (result == NULL) || (resultLen == NULL)) { 164 return DR_ParamErr; 165 } 166 if(*resultLen < totalLen) { 167 return DR_BufOverflow; 168 } 169 DERMemmove(result, encodedMdDigest, sizeof(encodedMdDigest)); 170 DERMemmove(result + sizeof(encodedMdDigest), mdDigest, DER_MD_DIGEST_LEN); 171 switch(whichDigest) { 172 case WD_MD2: 173 result[WHICH_DIGEST_INDEX] = WHICH_DIGEST_MD2; 174 break; 175 case WD_MD5: 176 result[WHICH_DIGEST_INDEX] = WHICH_DIGEST_MD5; 177 break; 178 default: 179 return DR_ParamErr; 180 } 181 *resultLen = totalLen; 182 return DR_Success; 183} 184