1f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* LibTomCrypt, modular cryptographic library -- Tom St Denis 2f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 3f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * LibTomCrypt is a library that provides various cryptographic 4f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * algorithms in a highly modular and flexible manner. 5f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 6f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The library is free for all purposes without any express 7f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * guarantee it works. 8f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 9f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com 10f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 11f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "tomcrypt.h" 12f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 13f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/** 14f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @file der_decode_choice.c 15f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ASN.1 DER, decode a CHOICE, Tom St Denis 16f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/ 17f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 18f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_DER 19f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 20f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/** 21f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project Decode a CHOICE 22f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param in The DER encoded input 23f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param inlen [in/out] The size of the input and resulting size of read type 24f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param list The list of items to decode 25f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param outlen The number of items in the list 26f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @return CRYPT_OK on success 27f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/ 28f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint der_decode_choice(const unsigned char *in, unsigned long *inlen, 29f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ltc_asn1_list *list, unsigned long outlen) 30f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 31f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned long size, x, z; 32f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project void *data; 33f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 34f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(in != NULL); 35f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(inlen != NULL); 36f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(list != NULL); 37f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 38f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* get blk size */ 39f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (*inlen < 2) { 40f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_INVALID_PACKET; 41f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 42f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 43f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* set all of the "used" flags to zero */ 44f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (x = 0; x < outlen; x++) { 45f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project list[x].used = 0; 46f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 47f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 48f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* now scan until we have a winner */ 49f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (x = 0; x < outlen; x++) { 50f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project size = list[x].size; 51f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project data = list[x].data; 52f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 53f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project switch (list[x].type) { 54f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project case LTC_ASN1_INTEGER: 55f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (der_decode_integer(in, *inlen, data) == CRYPT_OK) { 56f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (der_length_integer(data, &z) == CRYPT_OK) { 57f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project list[x].used = 1; 58f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *inlen = z; 59f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_OK; 60f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 61f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 62f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project break; 63f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 64f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project case LTC_ASN1_SHORT_INTEGER: 65f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (der_decode_short_integer(in, *inlen, data) == CRYPT_OK) { 66f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (der_length_short_integer(size, &z) == CRYPT_OK) { 67f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project list[x].used = 1; 68f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *inlen = z; 69f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_OK; 70f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 71f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 72f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project break; 73f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 74f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project case LTC_ASN1_BIT_STRING: 75f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (der_decode_bit_string(in, *inlen, data, &size) == CRYPT_OK) { 76f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (der_length_bit_string(size, &z) == CRYPT_OK) { 77f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project list[x].used = 1; 78f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project list[x].size = size; 79f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *inlen = z; 80f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_OK; 81f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 82f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 83f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project break; 84f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 85f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project case LTC_ASN1_OCTET_STRING: 86f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (der_decode_octet_string(in, *inlen, data, &size) == CRYPT_OK) { 87f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (der_length_octet_string(size, &z) == CRYPT_OK) { 88f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project list[x].used = 1; 89f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project list[x].size = size; 90f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *inlen = z; 91f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_OK; 92f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 93f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 94f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project break; 95f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 96f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project case LTC_ASN1_NULL: 97f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (*inlen == 2 && in[x] == 0x05 && in[x+1] == 0x00) { 98f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *inlen = 2; 99f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project list[x].used = 1; 100f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_OK; 101f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 102f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project break; 103f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 104f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project case LTC_ASN1_OBJECT_IDENTIFIER: 105f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (der_decode_object_identifier(in, *inlen, data, &size) == CRYPT_OK) { 106f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (der_length_object_identifier(data, size, &z) == CRYPT_OK) { 107f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project list[x].used = 1; 108f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project list[x].size = size; 109f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *inlen = z; 110f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_OK; 111f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 112f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 113f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project break; 114f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 115f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project case LTC_ASN1_IA5_STRING: 116f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (der_decode_ia5_string(in, *inlen, data, &size) == CRYPT_OK) { 117f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (der_length_ia5_string(data, size, &z) == CRYPT_OK) { 118f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project list[x].used = 1; 119f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project list[x].size = size; 120f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *inlen = z; 121f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_OK; 122f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 123f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 124f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project break; 125f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 126f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 127f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project case LTC_ASN1_PRINTABLE_STRING: 128f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (der_decode_printable_string(in, *inlen, data, &size) == CRYPT_OK) { 129f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (der_length_printable_string(data, size, &z) == CRYPT_OK) { 130f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project list[x].used = 1; 131f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project list[x].size = size; 132f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *inlen = z; 133f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_OK; 134f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 135f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 136f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project break; 137f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 138f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project case LTC_ASN1_UTF8_STRING: 139f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (der_decode_utf8_string(in, *inlen, data, &size) == CRYPT_OK) { 140f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (der_length_utf8_string(data, size, &z) == CRYPT_OK) { 141f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project list[x].used = 1; 142f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project list[x].size = size; 143f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *inlen = z; 144f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_OK; 145f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 146f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 147f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project break; 148f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 149f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project case LTC_ASN1_UTCTIME: 150f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project z = *inlen; 151f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (der_decode_utctime(in, &z, data) == CRYPT_OK) { 152f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project list[x].used = 1; 153f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *inlen = z; 154f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_OK; 155f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 156f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project break; 157f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 158f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project case LTC_ASN1_SET: 159f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project case LTC_ASN1_SETOF: 160f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project case LTC_ASN1_SEQUENCE: 161f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (der_decode_sequence(in, *inlen, data, size) == CRYPT_OK) { 162f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (der_length_sequence(data, size, &z) == CRYPT_OK) { 163f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project list[x].used = 1; 164f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *inlen = z; 165f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_OK; 166f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 167f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 168f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project break; 169f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 170f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project default: 171f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_INVALID_ARG; 172f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 173f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 174f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 175f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_INVALID_PACKET; 176f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 177f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 178f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 179f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 180f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c,v $ */ 181f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Revision: 1.8 $ */ 182f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Date: 2006/12/06 02:23:49 $ */ 183