1/* 2 * Copyright (c) 2009,2012,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#include "DER_Ticket.h" 26 27#include <libDER/asn1Types.h> 28#include <libDER/DER_Decode.h> 29#include <libDER/DER_Encode.h> 30#include <libDER/DER_Keys.h> 31 32/* Application Processor Ticket */ 33const DERItemSpec DERApTicketItemSpecs[] = 34{ 35 { DER_OFFSET(DERApTicket, signatureAlgorithm), 36 ASN1_CONSTR_SEQUENCE, 37 DER_DEC_NO_OPTS | DER_ENC_WRITE_DER }, 38 { DER_OFFSET(DERApTicket, body), 39 ASN1_CONSTR_SET, 40 DER_DEC_NO_OPTS | DER_DEC_SAVE_DER | DER_ENC_WRITE_DER }, 41 { DER_OFFSET(DERApTicket, signature), 42 ASN1_OCTET_STRING, 43 DER_DEC_NO_OPTS }, 44 { DER_OFFSET(DERApTicket, certificates), 45 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1, 46 DER_DEC_NO_OPTS | DER_ENC_WRITE_DER } 47}; 48const DERSize DERNumApTicketItemSpecs = 49 sizeof(DERApTicketItemSpecs) / sizeof(DERItemSpec); 50 51/* Baseband Ticket */ 52const DERItemSpec DERBbTicketItemSpecs[] = 53{ 54 { DER_OFFSET(DERBbTicket, signatureAlgorithm), 55 ASN1_CONSTR_SEQUENCE, 56 DER_DEC_NO_OPTS | DER_ENC_WRITE_DER }, 57 { DER_OFFSET(DERBbTicket, body), 58 ASN1_CONSTR_SET, 59 DER_DEC_NO_OPTS | DER_DEC_SAVE_DER | DER_ENC_WRITE_DER }, 60 { DER_OFFSET(DERBbTicket, signature), 61 ASN1_OCTET_STRING, 62 DER_DEC_NO_OPTS }, 63 { DER_OFFSET(DERBbTicket, gpuk), 64 ASN1_CONTEXT_SPECIFIC | 2, 65 DER_DEC_NO_OPTS } 66}; 67const DERSize DERNumBbTicketItemSpecs = 68 sizeof(DERBbTicketItemSpecs) / sizeof(DERItemSpec); 69 70#if 0 71/* We need to verify this value and use it here. */ 72const DERByte rsaWithSha1Algorithm[] = { 73 0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05 74}; 75#endif 76 77#ifdef FAST_SET_LOOKUP 78/* Iterates over all the tags in the set to build an index returned in 79 derSet. */ 80DERReturn DERDecodeSetContentInit( 81 const DERItem *content, /* data to decode */ 82 DERSet *derSet) /* IN/OUT, to use in DERDecodeSetTag */ 83{ 84 DERReturn drtn; 85 DERSequence derSeq; 86 memset(derSet->byTag, 0, derSet->capacity); 87 drtn = DERDecodeSeqContentInit(content, &derSeq); 88 if (drtn == DR_Success) { 89 DERDecodedInfo element; 90 while ((drtn = DERDecodeSeqNext(&derSeq, &element)) == DR_Success) { 91 if (element.tag >= derSet->capacity) return DR_UnexpectedTag; 92 derSet->byTag[element.tag] = element.content.data; 93 } 94 if (drtn == DR_EndOfSequence) drtn = DR_Success; 95 } 96 derSet->end = content->data + content->length; 97 98 return drtn; 99} 100 101DERReturn DERDecodeSetTag( 102 DERSet *derSet, /* data to decode */ 103 DERTag tag, /* tag in sequence/set we are looking for. */ 104 DERItem *content) /* RETURNED */ 105{ 106 DERReturn drtn; 107 DERTag tagNumber = tag & ASN1_TAGNUM_MASK; 108 if (tagNumber > derSet->capacity) 109 return DR_UnexpectedTag; 110 DERByte *start = derSet->byTag[tagNumber]; 111 if (!start) return DR_UnexpectedTag; 112 DERItem derItem = { .data = start, .length = derSet->end - start }; 113 DERDecodedInfo element; 114 drtn = DERDecodeItem(&derItem, &element); 115 if (drtn) return drtn; 116 if (tag != element.tag) return DR_UnexpectedTag; 117 *content = element.content; 118 119 return drtn; 120} 121#endif /* FAST_SET_LOOKUP */ 122 123/* Returns the item with tag from the sequence or set pointed to by der. 124 result DR_EndOfSequence if the tag was not found. */ 125DERReturn DERSetDecodeItemWithTag( 126 const DERItem *der, /* data to decode */ 127 DERTag tag, /* tag in sequence/set we are looking for. */ 128 DERItem *content) /* RETURNED */ 129{ 130 DERReturn drtn; 131 DERSequence derSeq; 132 DERTag topTag; 133 drtn = DERDecodeSeqInit(der, &topTag, &derSeq); 134 if (drtn == DR_Success) { 135 DERDecodedInfo info; 136 while ((drtn = DERDecodeSeqNext(&derSeq, &info)) == DR_Success) { 137 if (info.tag == tag) { 138 *content = info.content; 139 return DR_Success; 140 } 141 } 142 } 143 144 return drtn; 145} 146 147DERReturn DERDecodeApTicket( 148 const DERItem *contents, 149 DERApTicket *ticket, /* RETURNED */ 150 DERSize *numUsedBytes) /* RETURNED */ 151{ 152 DERReturn drtn; 153 DERDecodedInfo decodedTicket; 154 drtn = DERDecodeItem(contents, &decodedTicket); 155 if (drtn != DR_Success) goto badTicket; 156 drtn = DERParseSequenceContent(&decodedTicket.content, 157 DERNumApTicketItemSpecs, DERApTicketItemSpecs, ticket, 0); 158 if (drtn != DR_Success) goto badTicket; 159 160 /* Decode the algorithm sequence. */ 161 DERAlgorithmId algorithm = {}; 162 drtn = DERParseSequenceContent(&ticket->signatureAlgorithm, 163 DERNumAlgorithmIdItemSpecs, DERAlgorithmIdItemSpecs, &algorithm, 0); 164 if (drtn != DR_Success) goto badTicket; 165 /* TODO Check algorithm oid and ensure there are no params. 166 Alternatively replace the code above with a simple memcmp with 167 an already ASN.1 encoded algorithm parms block. */ 168 169badTicket: 170 *numUsedBytes = decodedTicket.content.length + 171 decodedTicket.content.data - contents->data; 172 173 return drtn; 174} 175 176DERReturn DERDecodeBbTicket( 177 const DERItem *contents, 178 DERBbTicket *ticket, /* RETURNED */ 179 DERSize *numUsedBytes) /* RETURNED */ 180{ 181 DERReturn drtn; 182 DERDecodedInfo decodedTicket; 183 drtn = DERDecodeItem(contents, &decodedTicket); 184 if (drtn != DR_Success) goto badTicket; 185 drtn = DERParseSequenceContent(&decodedTicket.content, 186 DERNumBbTicketItemSpecs, DERBbTicketItemSpecs, ticket, 0); 187 if (drtn != DR_Success) goto badTicket; 188 189 /* Decode the algorithm sequence. */ 190 DERAlgorithmId algorithm = {}; 191 drtn = DERParseSequenceContent(&ticket->signatureAlgorithm, 192 DERNumAlgorithmIdItemSpecs, DERAlgorithmIdItemSpecs, &algorithm, 0); 193 if (drtn != DR_Success) goto badTicket; 194 /* TODO Check algorithm oid and ensure there are no params. 195 Alternatively replace the code above with a simple memcmp with 196 an already ASN.1 encoded algorithm parms block. */ 197 198badTicket: 199 *numUsedBytes = decodedTicket.content.length + 200 decodedTicket.content.data - contents->data; 201 202 return drtn; 203} 204