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