1/* 2 * Copyright (c) 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 * tsaDERUtilities.c - ASN1 templates Time Stamping Authority requests and responses. 24 * see rfc3161.asn1 for ASN.1 and other comments 25 */ 26 27#include <libDER/asn1Types.h> 28#include <libDER/DER_Decode.h> 29#include <AssertMacros.h> 30#include <Security/cssmtype.h> 31#include <stdlib.h> 32#include "tsaDERUtilities.h" 33 34#ifndef DER_MULTIBYTE_TAGS 35#error We expect DER_MULTIBYTE_TAGS 36#endif 37 38/* PKIStatusInfo */ 39typedef struct { 40 DERItem status; // INTEGER 41 DERItem statusString; // UTF8_STRING | SEC_ASN1_OPTIONAL 42 DERItem failInfo; // BIT_STRING | SEC_ASN1_OPTIONAL 43} DERPKIStatusInfo; 44 45/* xx */ 46typedef struct { 47 DERItem statusString; // UTF8_STRING | SEC_ASN1_OPTIONAL 48} DERPKIStatusStringInner; 49 50/* TimeStampResp */ 51typedef struct 52{ 53 DERItem status; /* PKIStatusInfo */ 54 DERItem timeStampToken; /* TimeStampToken */ 55} DERTimeStampResp; 56 57/* TimeStampResp */ 58const DERItemSpec DERTimeStampRespItemSpecs[] = 59{ 60 { DER_OFFSET(DERTimeStampResp, status), 61 ASN1_CONSTR_SEQUENCE, DER_DEC_NO_OPTS }, 62 { DER_OFFSET(DERTimeStampResp, timeStampToken), 63 ASN1_CONSTR_SEQUENCE, DER_DEC_NO_OPTS | DER_DEC_OPTIONAL | DER_DEC_SAVE_DER} 64}; 65const DERSize DERNumTimeStampRespItemSpecs = sizeof(DERTimeStampRespItemSpecs) / sizeof(DERItemSpec); 66 67/* 68 This code is here rather than in libsecurity_smime because 69 libsecurity_smime doesn't know about libDER 70*/ 71 72int DERDecodeTimeStampResponse( 73 const CSSM_DATA *contents, 74 CSSM_DATA *derStatus, 75 CSSM_DATA *derTimeStampToken, 76 size_t *numUsedBytes) /* RETURNED */ 77{ 78 DERReturn drtn = DR_ParamErr; 79 DERDecodedInfo decodedPackage; 80 81 if (contents) 82 { 83 DERItem derContents = {.data = contents->Data, .length = contents->Length }; 84 DERTimeStampResp derResponse = {{0,},{0,}}; 85 DERReturn rx; 86 require_noerr(DERDecodeItem(&derContents, &decodedPackage), badResponse); 87 88 rx = DERParseSequenceContent(&decodedPackage.content, 89 DERNumTimeStampRespItemSpecs, DERTimeStampRespItemSpecs, 90 &derResponse, 0); 91 if (rx != DR_Success) 92 goto badResponse; 93/* 94 require_noerr(DERParseSequenceContent(&decodedPackage.content, 95 DERNumTimeStampRespItemSpecs, DERTimeStampRespItemSpecs, 96 &derResponse, 0), badResponse); 97*/ 98 if (derStatus && derResponse.status.data) 99 { 100 derStatus->Data = malloc(derResponse.status.length); 101 derStatus->Length = derResponse.status.length; 102 memcpy(derStatus->Data, derResponse.status.data, derStatus->Length); 103 } 104 if (derTimeStampToken && derResponse.timeStampToken.data) 105 { 106 derTimeStampToken->Data = malloc(derResponse.timeStampToken.length); 107 derTimeStampToken->Length = derResponse.timeStampToken.length; 108 memcpy(derTimeStampToken->Data, derResponse.timeStampToken.data, derTimeStampToken->Length); 109 } 110 } 111 112 drtn = DR_Success; 113 114badResponse: 115 if (numUsedBytes) 116 *numUsedBytes = decodedPackage.content.length + 117 decodedPackage.content.data - contents->Data; 118 119 return drtn; 120} 121 122