
/* ****************************************************************************

 * eID Middleware Project.
 * Copyright (C) 2008-2012 FedICT.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version
 * 3.0 as published by the Free Software Foundation.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, see
 * http://www.gnu.org/licenses/.

**************************************************************************** */
#ifndef EIDMW_ASN1_H
#define EIDMW_ASN1_H

#ifdef __cplusplus
extern "C"
{
#endif

/* return codes for ASN1 parsing */
#define E_ASN_BAD_TAG        -1	/* tag not expected or unknown */
#define E_ASN_TAG_LEN        -2	/* tag has length > 4 bytes */
#define E_ASN_BAD_LEN        -3	/* length encoding error */
#define E_ASN_INCOMPLETE     -4	/* unexpected end of ASN1 encoding */
#define E_ASN_ITEM_NOT_FOUND -5	/* item in path does not exist */
#define E_ASN_ALLOC          -6	/* memory allocation error */
#define E_ASN_LIST           -7	/* error in asn1 item list to encode */
//#define ASN1_ERR -1


	typedef struct ASN1_ITEM
	{
		unsigned int tag;	//tag
		const unsigned char *p_data;	//value data
		unsigned int l_data;	//value len
		unsigned int nsubitems;	//number of sub-items (not yet implemented !, always 0)
		const unsigned char *p_raw;	//total TLV data
		unsigned int l_raw;	//total TLV len
	} ASN1_ITEM;


	typedef struct ASN1_LIST
	{
		unsigned int size;
		unsigned int nitems;
		ASN1_ITEM *item;
	} ASN1_LIST;



	typedef struct T_OID
	{
		char *dotid;
		char *str;
	} T_OID;



/* BER ASN1 decoding masks */
#define TAG_MASK   0x1F	     /* bits 1 - 5  */
#define TYPE_MASK  0x20	     /* bit  6      */
#define CLASS_MASK 0xC0	     /* bits 7,8    */

#define LEN_MASK   0x7F	     /* bits 1 - 7  */
#define EXT_LEN    0x80	     /* bit  8      */

/* For this implementation: class, type and tagnumber are converted to single unsigned int max 4 bytes (32-bit) */

/* 2 bits for class, 1 bit for type so 29 bits remain for tagnumber (32-bit system)    */

/* tag encoded as multiple of 7 bits cannot be bigger than 28 bits anyway */

/* following are the definitions for class, type and value */

/* ASN_CLASS: bit 1 and 2 */
#define ASN_UNIVERSAL    0x00
#define ASN_APPLICATION  0x01
#define ASN_CONTEXT      0x02
#define ASN_PRIVATE      0x03
#define ASN_CLASS        0x03

/* ASN_TYPE: bit 3 */
#define ASN_PRIMITIV     0x00
#define ASN_CONSTRUCTED  0x04
#define ASN_TYPE         0x04

/* COMMON ASN_TAGS */
//#define ASN_EOC               ( ASN_CONTEXT   | ASN_CONSTRUCTED | (0x00 << 3) )   /* end of contents octet */
#define ASN_BOOLEAN             ( ASN_UNIVERSAL | ASN_PRIMITIV    | (0x01 << 3) )
#define ASN_INTEGER             ( ASN_UNIVERSAL | ASN_PRIMITIV    | (0x02 << 3) )
#define ASN_BIT_STRING          ( ASN_UNIVERSAL | ASN_PRIMITIV    | (0x03 << 3) )
#define ASN_OCTET_STRING        ( ASN_UNIVERSAL | ASN_PRIMITIV    | (0x04 << 3) )
#define ASN_NULL                ( ASN_UNIVERSAL | ASN_PRIMITIV    | (0x05 << 3) )
#define ASN_OID                 ( ASN_UNIVERSAL | ASN_PRIMITIV    | (0x06 << 3) )
#define ASN_OBJDESCRIP          ( ASN_UNIVERSAL | ASN_PRIMITIV    | (0x07 << 3) )
#define ASN_EXTERNAL            ( ASN_UNIVERSAL | ASN_PRIMITIV    | (0x08 << 3) )
#define ASN_REAL                ( ASN_UNIVERSAL | ASN_PRIMITIV    | (0x09 << 3) )
#define ASN_ENUM                ( ASN_UNIVERSAL | ASN_PRIMITIV    | (0x0A << 3) )
#define ASN_EMBEDED_PDV         ( ASN_UNIVERSAL | ASN_PRIMITIV    | (0x0B << 3) )
#define ASN_UTF8STRING          ( ASN_UNIVERSAL | ASN_PRIMITIV    | (0x0C << 3) )

#define ASN_SEQUENCE            ( ASN_UNIVERSAL | ASN_CONSTRUCTED | (0x10 << 3) )
#define ASN_SET                 ( ASN_UNIVERSAL | ASN_CONSTRUCTED | (0x11 << 3) )
#define ASN_NUMSTRING           ( ASN_UNIVERSAL | ASN_CONSTRUCTED | (0x12 << 3) )
#define ASN_PRINTABLE_STRING    ( ASN_UNIVERSAL | ASN_PRIMITIV    | (0x13 << 3) )
#define ASN_T61STRING           ( ASN_UNIVERSAL | ASN_PRIMITIV    | (0x14 << 3) )
#define ASN_VIDEOTXTSTRING      ( ASN_UNIVERSAL | ASN_PRIMITIV    | (0x15 << 3) )
#define ASN_IA5STRING           ( ASN_UNIVERSAL | ASN_PRIMITIV    | (0x16 << 3) )
#define ASN_UTCTIME             ( ASN_UNIVERSAL | ASN_PRIMITIV    | (0x17 << 3) )
#define ASN_GENERALIZEDTIME     ( ASN_UNIVERSAL | ASN_PRIMITIV    | (0x18 << 3) )
#define ASN_GRAPHICSTRING       ( ASN_UNIVERSAL | ASN_PRIMITIV    | (0x19 << 3) )
#define ASN_VISIBLESTRING       ( ASN_UNIVERSAL | ASN_PRIMITIV    | (0x1A << 3) )
#define ASN_GENERALSTRING       ( ASN_UNIVERSAL | ASN_PRIMITIV    | (0x1B << 3) )
#define ASN_UNIVERSALSTRING     ( ASN_UNIVERSAL | ASN_PRIMITIV    | (0x1C << 3) )
#define ASN_BMPSTRING           ( ASN_UNIVERSAL | ASN_PRIMITIV    | (0x1E << 3) )
#define ASN_ANY                 ( ASN_UNIVERSAL | ASN_PRIMITIV    | (0xfffff << 3) )

#define ASNP15_DIRREC           ( ASN_APPLICATION | ASN_CONSTRUCTED | (01 << 3) )
#define ASNP15_DIRAID           ( ASN_APPLICATION | ASN_PRIMITIV    | (15 << 3) )
#define ASNP15_DIRLABEL         ( ASN_APPLICATION | ASN_PRIMITIV    | (16 << 3) )
#define ASNP15_DIRPATH          ( ASN_APPLICATION | ASN_PRIMITIV    | (17 << 3) )

/* ASN1 structured element */
#define ASN_SE(a)                    ( ASN_CONTEXT   | ASN_CONSTRUCTED   | (a << 3) )
#define ASN_CONSTRUCTED_CONTEXT_N(n) ( ASN_CONTEXT   | ASN_CONSTRUCTED   | (n << 3) )
#define ASN_PRIMITIVE_CONTEXT_N(n)   ( ASN_CONTEXT   | ASN_PRIMITIV      | (n << 3) )


#define OID_RSA_ENCRYPTION      "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01"
#define OID_EC_PUBLIC_KEY	"\x2A\x86\x48\xCE\x3D\x02\x01"
#define ASNPATH_FIRST           "\x01"

#define OID_SECP256R1		"\x2A\x86\x48\xCE\x3D\x03\x01\x07"
#define OID_SECP384R1		"\x2B\x81\x04\x00\x22"
#define OID_SECP521R1		"\x2B\x81\x04\x00\x23"
#define OID_BRAINPOOLP512R1	"\x2B\x24\x03\x03\x02\x08\x01\x01\x0D"

/* ASN1 decoding functions */
	int asn1_get_item(const unsigned char *content, unsigned int len,
			  const char *path, ASN1_ITEM * item, unsigned char ucParseBitString);
	int asn1_find_item(const unsigned char *content, unsigned int len,
			   unsigned int findtag, ASN1_ITEM * item);
	int dec_oid(unsigned char *p_data, int l_data, unsigned int *oid,
		    int l_oid);

	int asn1_next_item(ASN1_ITEM * p_xLev0,	      /**< In/out: object   */

			   ASN1_ITEM * p_xLev1	      /**< Out: object   */
		);

#ifdef __cplusplus
}
#endif


#endif
