220 lines
6.8 KiB
C
220 lines
6.8 KiB
C
|
/*
|
||
|
* 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_ */
|
||
|
|