andre@0: /* This Source Code Form is subject to the terms of the Mozilla Public andre@0: * License, v. 2.0. If a copy of the MPL was not distributed with this andre@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ andre@0: andre@0: /* andre@0: * Support for encoding/decoding of ASN.1 using BER/DER (Basic/Distinguished andre@0: * Encoding Rules). The routines are found in and used extensively by the andre@0: * security library, but exported for other use. andre@0: */ andre@0: andre@0: #ifndef _SECASN1_H_ andre@0: #define _SECASN1_H_ andre@0: andre@0: #include "utilrename.h" andre@0: #include "plarena.h" andre@0: andre@0: #include "seccomon.h" andre@0: #include "secasn1t.h" andre@0: andre@0: andre@0: /************************************************************************/ andre@0: SEC_BEGIN_PROTOS andre@0: andre@0: /* andre@0: * XXX These function prototypes need full, explanatory comments. andre@0: */ andre@0: andre@0: /* andre@0: ** Decoding. andre@0: */ andre@0: andre@0: extern SEC_ASN1DecoderContext *SEC_ASN1DecoderStart(PLArenaPool *pool, andre@0: void *dest, andre@0: const SEC_ASN1Template *t); andre@0: andre@0: /* XXX char or unsigned char? */ andre@0: extern SECStatus SEC_ASN1DecoderUpdate(SEC_ASN1DecoderContext *cx, andre@0: const char *buf, andre@0: unsigned long len); andre@0: andre@0: extern SECStatus SEC_ASN1DecoderFinish(SEC_ASN1DecoderContext *cx); andre@0: andre@0: /* Higher level code detected an error, abort the rest of the processing */ andre@0: extern void SEC_ASN1DecoderAbort(SEC_ASN1DecoderContext *cx, int error); andre@0: andre@0: extern void SEC_ASN1DecoderSetFilterProc(SEC_ASN1DecoderContext *cx, andre@0: SEC_ASN1WriteProc fn, andre@0: void *arg, PRBool no_store); andre@0: andre@0: extern void SEC_ASN1DecoderClearFilterProc(SEC_ASN1DecoderContext *cx); andre@0: andre@0: extern void SEC_ASN1DecoderSetNotifyProc(SEC_ASN1DecoderContext *cx, andre@0: SEC_ASN1NotifyProc fn, andre@0: void *arg); andre@0: andre@0: extern void SEC_ASN1DecoderClearNotifyProc(SEC_ASN1DecoderContext *cx); andre@0: andre@0: extern SECStatus SEC_ASN1Decode(PLArenaPool *pool, void *dest, andre@0: const SEC_ASN1Template *t, andre@0: const char *buf, long len); andre@0: andre@0: /* Both classic ASN.1 and QuickDER have a feature that removes leading zeroes andre@0: out of SEC_ASN1_INTEGER if the caller sets siUnsignedInteger in the type andre@0: field of the target SECItem prior to calling the decoder. Otherwise, the andre@0: type field is ignored and untouched. For SECItem that are dynamically andre@0: allocated (from POINTER, SET OF, SEQUENCE OF) the decoder sets the type andre@0: field to siBuffer. */ andre@0: andre@0: extern SECStatus SEC_ASN1DecodeItem(PLArenaPool *pool, void *dest, andre@0: const SEC_ASN1Template *t, andre@0: const SECItem *src); andre@0: andre@0: extern SECStatus SEC_QuickDERDecodeItem(PLArenaPool* arena, void* dest, andre@0: const SEC_ASN1Template* templateEntry, andre@0: const SECItem* src); andre@0: andre@0: /* andre@0: ** Encoding. andre@0: */ andre@0: andre@0: extern SEC_ASN1EncoderContext *SEC_ASN1EncoderStart(const void *src, andre@0: const SEC_ASN1Template *t, andre@0: SEC_ASN1WriteProc fn, andre@0: void *output_arg); andre@0: andre@0: /* XXX char or unsigned char? */ andre@0: extern SECStatus SEC_ASN1EncoderUpdate(SEC_ASN1EncoderContext *cx, andre@0: const char *buf, andre@0: unsigned long len); andre@0: andre@0: extern void SEC_ASN1EncoderFinish(SEC_ASN1EncoderContext *cx); andre@0: andre@0: /* Higher level code detected an error, abort the rest of the processing */ andre@0: extern void SEC_ASN1EncoderAbort(SEC_ASN1EncoderContext *cx, int error); andre@0: andre@0: extern void SEC_ASN1EncoderSetNotifyProc(SEC_ASN1EncoderContext *cx, andre@0: SEC_ASN1NotifyProc fn, andre@0: void *arg); andre@0: andre@0: extern void SEC_ASN1EncoderClearNotifyProc(SEC_ASN1EncoderContext *cx); andre@0: andre@0: extern void SEC_ASN1EncoderSetStreaming(SEC_ASN1EncoderContext *cx); andre@0: andre@0: extern void SEC_ASN1EncoderClearStreaming(SEC_ASN1EncoderContext *cx); andre@0: andre@0: extern void sec_ASN1EncoderSetDER(SEC_ASN1EncoderContext *cx); andre@0: andre@0: extern void sec_ASN1EncoderClearDER(SEC_ASN1EncoderContext *cx); andre@0: andre@0: extern void SEC_ASN1EncoderSetTakeFromBuf(SEC_ASN1EncoderContext *cx); andre@0: andre@0: extern void SEC_ASN1EncoderClearTakeFromBuf(SEC_ASN1EncoderContext *cx); andre@0: andre@0: extern SECStatus SEC_ASN1Encode(const void *src, const SEC_ASN1Template *t, andre@0: SEC_ASN1WriteProc output_proc, andre@0: void *output_arg); andre@0: andre@0: /* andre@0: * If both pool and dest are NULL, the caller should free the returned SECItem andre@0: * with a SECITEM_FreeItem(..., PR_TRUE) call. If pool is NULL but dest is andre@0: * not NULL, the caller should free the data buffer pointed to by dest with a andre@0: * SECITEM_FreeItem(dest, PR_FALSE) or PORT_Free(dest->data) call. andre@0: */ andre@0: extern SECItem * SEC_ASN1EncodeItem(PLArenaPool *pool, SECItem *dest, andre@0: const void *src, const SEC_ASN1Template *t); andre@0: andre@0: extern SECItem * SEC_ASN1EncodeInteger(PLArenaPool *pool, andre@0: SECItem *dest, long value); andre@0: andre@0: extern SECItem * SEC_ASN1EncodeUnsignedInteger(PLArenaPool *pool, andre@0: SECItem *dest, andre@0: unsigned long value); andre@0: andre@0: extern SECStatus SEC_ASN1DecodeInteger(SECItem *src, andre@0: unsigned long *value); andre@0: andre@0: /* andre@0: ** Utilities. andre@0: */ andre@0: andre@0: /* andre@0: * We have a length that needs to be encoded; how many bytes will the andre@0: * encoding take? andre@0: */ andre@0: extern int SEC_ASN1LengthLength (unsigned long len); andre@0: andre@0: /* encode the length and return the number of bytes we encoded. Buffer andre@0: * must be pre allocated */ andre@0: extern int SEC_ASN1EncodeLength(unsigned char *buf,int value); andre@0: andre@0: /* andre@0: * Find the appropriate subtemplate for the given template. andre@0: * This may involve calling a "chooser" function, or it may just andre@0: * be right there. In either case, it is expected to *have* a andre@0: * subtemplate; this is asserted in debug builds (in non-debug andre@0: * builds, NULL will be returned). andre@0: * andre@0: * "thing" is a pointer to the structure being encoded/decoded andre@0: * "encoding", when true, means that we are in the process of encoding andre@0: * (as opposed to in the process of decoding) andre@0: */ andre@0: extern const SEC_ASN1Template * andre@0: SEC_ASN1GetSubtemplate (const SEC_ASN1Template *inTemplate, void *thing, andre@0: PRBool encoding); andre@0: andre@0: /* whether the template is for a primitive type or a choice of andre@0: * primitive types andre@0: */ andre@0: extern PRBool SEC_ASN1IsTemplateSimple(const SEC_ASN1Template *theTemplate); andre@0: andre@0: /************************************************************************/ andre@0: andre@0: /* andre@0: * Generic Templates andre@0: * One for each of the simple types, plus a special one for ANY, plus: andre@0: * - a pointer to each one of those andre@0: * - a set of each one of those andre@0: * - a sequence of each one of those andre@0: * andre@0: * Note that these are alphabetical (case insensitive); please add new andre@0: * ones in the appropriate place. andre@0: */ andre@0: andre@0: extern const SEC_ASN1Template SEC_AnyTemplate[]; andre@0: extern const SEC_ASN1Template SEC_BitStringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_BMPStringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_BooleanTemplate[]; andre@0: extern const SEC_ASN1Template SEC_EnumeratedTemplate[]; andre@0: extern const SEC_ASN1Template SEC_GeneralizedTimeTemplate[]; andre@0: extern const SEC_ASN1Template SEC_IA5StringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_IntegerTemplate[]; andre@0: extern const SEC_ASN1Template SEC_NullTemplate[]; andre@0: extern const SEC_ASN1Template SEC_ObjectIDTemplate[]; andre@0: extern const SEC_ASN1Template SEC_OctetStringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_PrintableStringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_T61StringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_UniversalStringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_UTCTimeTemplate[]; andre@0: extern const SEC_ASN1Template SEC_UTF8StringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_VisibleStringTemplate[]; andre@0: andre@0: extern const SEC_ASN1Template SEC_PointerToAnyTemplate[]; andre@0: extern const SEC_ASN1Template SEC_PointerToBitStringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_PointerToBMPStringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_PointerToBooleanTemplate[]; andre@0: extern const SEC_ASN1Template SEC_PointerToEnumeratedTemplate[]; andre@0: extern const SEC_ASN1Template SEC_PointerToGeneralizedTimeTemplate[]; andre@0: extern const SEC_ASN1Template SEC_PointerToIA5StringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_PointerToIntegerTemplate[]; andre@0: extern const SEC_ASN1Template SEC_PointerToNullTemplate[]; andre@0: extern const SEC_ASN1Template SEC_PointerToObjectIDTemplate[]; andre@0: extern const SEC_ASN1Template SEC_PointerToOctetStringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_PointerToPrintableStringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_PointerToT61StringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_PointerToUniversalStringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_PointerToUTCTimeTemplate[]; andre@0: extern const SEC_ASN1Template SEC_PointerToUTF8StringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_PointerToVisibleStringTemplate[]; andre@0: andre@0: extern const SEC_ASN1Template SEC_SequenceOfAnyTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SequenceOfBitStringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SequenceOfBMPStringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SequenceOfBooleanTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SequenceOfEnumeratedTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SequenceOfGeneralizedTimeTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SequenceOfIA5StringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SequenceOfIntegerTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SequenceOfNullTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SequenceOfObjectIDTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SequenceOfOctetStringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SequenceOfPrintableStringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SequenceOfT61StringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SequenceOfUniversalStringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SequenceOfUTCTimeTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SequenceOfUTF8StringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SequenceOfVisibleStringTemplate[]; andre@0: andre@0: extern const SEC_ASN1Template SEC_SetOfAnyTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SetOfBitStringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SetOfBMPStringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SetOfBooleanTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SetOfEnumeratedTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SetOfGeneralizedTimeTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SetOfIA5StringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SetOfIntegerTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SetOfNullTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SetOfObjectIDTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SetOfOctetStringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SetOfPrintableStringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SetOfT61StringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SetOfUniversalStringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SetOfUTCTimeTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SetOfUTF8StringTemplate[]; andre@0: extern const SEC_ASN1Template SEC_SetOfVisibleStringTemplate[]; andre@0: andre@0: /* andre@0: * Template for skipping a subitem; this only makes sense when decoding. andre@0: */ andre@0: extern const SEC_ASN1Template SEC_SkipTemplate[]; andre@0: andre@0: /* These functions simply return the address of the above-declared templates. andre@0: ** This is necessary for Windows DLLs. Sigh. andre@0: */ andre@0: SEC_ASN1_CHOOSER_DECLARE(SEC_AnyTemplate) andre@0: SEC_ASN1_CHOOSER_DECLARE(SEC_BMPStringTemplate) andre@0: SEC_ASN1_CHOOSER_DECLARE(SEC_BooleanTemplate) andre@0: SEC_ASN1_CHOOSER_DECLARE(SEC_BitStringTemplate) andre@0: SEC_ASN1_CHOOSER_DECLARE(SEC_GeneralizedTimeTemplate) andre@0: SEC_ASN1_CHOOSER_DECLARE(SEC_IA5StringTemplate) andre@0: SEC_ASN1_CHOOSER_DECLARE(SEC_IntegerTemplate) andre@0: SEC_ASN1_CHOOSER_DECLARE(SEC_NullTemplate) andre@0: SEC_ASN1_CHOOSER_DECLARE(SEC_ObjectIDTemplate) andre@0: SEC_ASN1_CHOOSER_DECLARE(SEC_OctetStringTemplate) andre@0: SEC_ASN1_CHOOSER_DECLARE(SEC_UTCTimeTemplate) andre@0: SEC_ASN1_CHOOSER_DECLARE(SEC_UTF8StringTemplate) andre@0: andre@0: SEC_ASN1_CHOOSER_DECLARE(SEC_PointerToAnyTemplate) andre@0: SEC_ASN1_CHOOSER_DECLARE(SEC_PointerToOctetStringTemplate) andre@0: andre@0: SEC_ASN1_CHOOSER_DECLARE(SEC_SetOfAnyTemplate) andre@0: andre@0: SEC_ASN1_CHOOSER_DECLARE(SEC_EnumeratedTemplate) andre@0: SEC_ASN1_CHOOSER_DECLARE(SEC_PointerToEnumeratedTemplate) andre@0: SEC_ASN1_CHOOSER_DECLARE(SEC_SequenceOfAnyTemplate) andre@0: SEC_ASN1_CHOOSER_DECLARE(SEC_SequenceOfObjectIDTemplate) andre@0: SEC_ASN1_CHOOSER_DECLARE(SEC_SkipTemplate) andre@0: SEC_ASN1_CHOOSER_DECLARE(SEC_UniversalStringTemplate) andre@0: SEC_ASN1_CHOOSER_DECLARE(SEC_PrintableStringTemplate) andre@0: SEC_ASN1_CHOOSER_DECLARE(SEC_T61StringTemplate) andre@0: SEC_ASN1_CHOOSER_DECLARE(SEC_PointerToGeneralizedTimeTemplate) andre@0: SEC_END_PROTOS andre@0: #endif /* _SECASN1_H_ */