• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Microsoft Reference Implementation for TPM 2.0
2  *
3  *  The copyright in this software is being made available under the BSD License,
4  *  included below. This software may be subject to other third party and
5  *  contributor rights, including patent rights, and no such rights are granted
6  *  under this license.
7  *
8  *  Copyright (c) Microsoft Corporation
9  *
10  *  All rights reserved.
11  *
12  *  BSD License
13  *
14  *  Redistribution and use in source and binary forms, with or without modification,
15  *  are permitted provided that the following conditions are met:
16  *
17  *  Redistributions of source code must retain the above copyright notice, this list
18  *  of conditions and the following disclaimer.
19  *
20  *  Redistributions in binary form must reproduce the above copyright notice, this
21  *  list of conditions and the following disclaimer in the documentation and/or
22  *  other materials provided with the distribution.
23  *
24  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28  *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29  *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31  *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 //** Includes
36 #include "Tpm.h"
37 #define _OIDS_
38 #include "OIDs.h"
39 #include "TpmASN1.h"
40 #include "TpmASN1_fp.h"
41 
42 //** Unmarshaling Functions
43 
44 //*** ASN1UnmarshalContextInitialize()
45 // Function does standard initialization of a context.
46 //  Return Type: BOOL
47 //      TRUE(1)     success
48 //      FALSE(0)    failure
49 BOOL
ASN1UnmarshalContextInitialize(ASN1UnmarshalContext * ctx,INT16 size,BYTE * buffer)50 ASN1UnmarshalContextInitialize(
51     ASN1UnmarshalContext    *ctx,
52     INT16                    size,
53     BYTE                    *buffer
54 )
55 {
56     VERIFY(buffer != NULL);
57     VERIFY(size > 0);
58     ctx->buffer = buffer;
59     ctx->size = size;
60     ctx->offset = 0;
61     ctx->tag = 0xFF;
62     return TRUE;
63 Error:
64     return FALSE;
65 }
66 
67 //***ASN1DecodeLength()
68 // This function extracts the length of an element from 'buffer' starting at 'offset'.
69 // Return Type: UINT16
70 //      >=0         the extracted length
71 //      <0          an error
72 INT16
ASN1DecodeLength(ASN1UnmarshalContext * ctx)73 ASN1DecodeLength(
74     ASN1UnmarshalContext        *ctx
75 )
76 {
77     BYTE                first;                  // Next octet in buffer
78     INT16               value;
79 //
80     VERIFY(ctx->offset < ctx->size);
81     first = NEXT_OCTET(ctx);
82     // If the number of octets of the entity is larger than 127, then the first octet
83     // is the number of octets in the length specifier.
84     if(first >= 0x80)
85     {
86         // Make sure that this length field is contained with the structure being
87         // parsed
88         CHECK_SIZE(ctx, (first & 0x7F));
89         if(first == 0x82)
90         {
91             // Two octets of size
92             // get the next value
93             value = (INT16)NEXT_OCTET(ctx);
94             // Make sure that the result will fit in an INT16
95             VERIFY(value < 0x0080);
96             // Shift up and add next octet
97             value = (value << 8) + NEXT_OCTET(ctx);
98         }
99         else if(first == 0x81)
100             value = NEXT_OCTET(ctx);
101         // Sizes larger than will fit in a INT16 are an error
102         else
103             goto Error;
104     }
105     else
106         value = first;
107     // Make sure that the size defined something within the current context
108     CHECK_SIZE(ctx, value);
109     return value;
110 Error:
111     ctx->size = -1;             // Makes everything fail from now on.
112     return -1;
113 }
114 
115 //***ASN1NextTag()
116 // This function extracts the next type from 'buffer' starting at 'offset'.
117 // It advances 'offset' as it parses the type and the length of the type. It returns
118 // the length of the type. On return, the 'length' octets starting at 'offset' are the
119 // octets of the type.
120 // Return Type: UINT
121 //     >=0          the number of octets in 'type'
122 //     <0           an error
123 INT16
ASN1NextTag(ASN1UnmarshalContext * ctx)124 ASN1NextTag(
125     ASN1UnmarshalContext    *ctx
126 )
127 {
128     // A tag to get?
129     VERIFY(ctx->offset < ctx->size);
130     // Get it
131     ctx->tag = NEXT_OCTET(ctx);
132     // Make sure that it is not an extended tag
133     VERIFY((ctx->tag & 0x1F) != 0x1F);
134     // Get the length field and return that
135     return ASN1DecodeLength(ctx);
136 
137 Error:
138     // Attempt to read beyond the end of the context or an illegal tag
139     ctx->size = -1;         // Persistent failure
140     ctx->tag = 0xFF;
141     return -1;
142 }
143 
144 
145 //*** ASN1GetBitStringValue()
146 // Try to parse a bit string of up to 32 bits from a value that is expected to be
147 // a bit string. The bit string is left justified so that the MSb of the input is
148 // the MSb of the returned value.
149 // If there is a general parsing error, the context->size is set to -1.
150 //  Return Type: BOOL
151 //      TRUE(1)     success
152 //      FALSE(0)    failure
153 BOOL
ASN1GetBitStringValue(ASN1UnmarshalContext * ctx,UINT32 * val)154 ASN1GetBitStringValue(
155     ASN1UnmarshalContext        *ctx,
156     UINT32                      *val
157 )
158 {
159     int                  shift;
160     INT16                length;
161     UINT32               value = 0;
162     int                  inputBits;
163 //
164     length = ASN1NextTag(ctx);
165     VERIFY(length >= 1);
166     VERIFY(ctx->tag == ASN1_BITSTRING);
167     // Get the shift value for the bit field (how many bits to lop off of the end)
168     shift = NEXT_OCTET(ctx);
169     length--;
170     // Get the number of bits in the input
171     inputBits = (8 * length) - shift;
172     // the shift count has to make sense
173     VERIFY((shift < 8) && ((length > 0) || (shift == 0)));
174     // if there are any bytes left
175     for(; length > 1; length--)
176     {
177 
178         // for all but the last octet, just shift and add the new octet
179         VERIFY((value & 0xFF000000) == 0); // can't loose significant bits
180         value = (value << 8) + NEXT_OCTET(ctx);
181 
182     }
183     if(length == 1)
184     {
185         // for the last octet, just shift the accumulated value enough to
186         // accept the significant bits in the last octet and shift the last
187         // octet down
188         VERIFY(((value & (0xFF000000 << (8 - shift)))) == 0);
189         value = (value << (8 - shift)) + (NEXT_OCTET(ctx) >> shift);
190 
191     }
192     // 'Left justify' the result
193     if(inputBits > 0)
194         value <<= (32 - inputBits);
195     *val = value;
196     return TRUE;
197 Error:
198     ctx->size = -1;
199     return FALSE;
200 }
201 
202 //*******************************************************************
203 //** Marshaling Functions
204 //*******************************************************************
205 
206 //*** Introduction
207 // Marshaling of an ASN.1 structure is accomplished from the bottom up. That is,
208 // the things that will be at the end of the structure are added last. To manage the
209 // collecting of the relative sizes, start a context for the outermost container, if
210 // there is one, and then placing items in from the bottom up. If the bottom-most
211 // item is also within a structure, create a nested context by calling
212 // ASN1StartMarshalingContext().
213 //
214 // The context control structure contains a 'buffer' pointer, an 'offset', an 'end'
215 // and a stack. 'offset' is the offset from the start of the buffer of the last added
216 // byte. When 'offset' reaches 0, the buffer is full. 'offset' is a signed value so
217 // that, when it becomes negative, there is an overflow. Only two functions are
218 // allowed to move bytes into the buffer: ASN1PushByte() and ASN1PushBytes(). These
219 // functions make sure that no data is written beyond the end of the buffer.
220 //
221 // When a new context is started, the current value of 'end' is pushed
222 // on the stack and 'end' is set to 'offset. As bytes are added, offset gets smaller.
223 // At any time, the count of bytes in the current context is simply 'end' - 'offset'.
224 //
225 // Since starting a new context involves setting 'end' = 'offset', the number of bytes
226 // in the context starts at 0. The nominal way of ending a context is to use
227 // 'end' - 'offset' to set the length value, and then a tag is added to the buffer.
228 // Then the previous 'end' value is popped meaning that the context just ended
229 // becomes a member of the now current context.
230 //
231 // The nominal strategy for building a completed ASN.1 structure is to push everything
232 // into the buffer and then move everything to the start of the buffer. The move is
233 // simple as the size of the move is the initial 'end' value minus the final 'offset'
234 // value. The destination is 'buffer' and the source is 'buffer' + 'offset'. As Skippy
235 // would say "Easy peasy, Joe."
236 //
237 // It is not necessary to provide a buffer into which the data is placed. If no buffer
238 // is provided, then the marshaling process will return values needed for marshaling.
239 // On strategy for filling the buffer would be to execute the process for building
240 // the structure without using a buffer. This would return the overall size of the
241 // structure. Then that amount of data could be allocated for the buffer and the fill
242 // process executed again with the data going into the buffer. At the end, the data
243 // would be in its final resting place.
244 
245 //*** ASN1InitialializeMarshalContext()
246 // This creates a structure for handling marshaling of an ASN.1 formatted data
247 // structure.
248 void
ASN1InitialializeMarshalContext(ASN1MarshalContext * ctx,INT16 length,BYTE * buffer)249 ASN1InitialializeMarshalContext(
250     ASN1MarshalContext      *ctx,
251     INT16                    length,
252     BYTE                    *buffer
253 )
254 {
255     ctx->buffer = buffer;
256     if(buffer)
257         ctx->offset = length;
258     else
259         ctx->offset = INT16_MAX;
260     ctx->end = ctx->offset;
261     ctx->depth = -1;
262 }
263 
264 //*** ASN1StartMarshalContext()
265 // This starts a new constructed element. It is constructed on 'top' of the value
266 // that was previously placed in the structure.
267 void
ASN1StartMarshalContext(ASN1MarshalContext * ctx)268 ASN1StartMarshalContext(
269     ASN1MarshalContext      *ctx
270 )
271 {
272     pAssert((ctx->depth + 1) < MAX_DEPTH);
273     ctx->depth++;
274     ctx->ends[ctx->depth] = ctx->end;
275     ctx->end = ctx->offset;
276 }
277 
278 //*** ASN1EndMarshalContext()
279 // This function restores the end pointer for an encapsulating structure.
280 //  Return Type: INT16
281 //      > 0             the size of the encapsulated structure that was just ended
282 //      <= 0            an error
283 INT16
ASN1EndMarshalContext(ASN1MarshalContext * ctx)284 ASN1EndMarshalContext(
285     ASN1MarshalContext      *ctx
286 )
287 {
288     INT16                   length;
289     pAssert(ctx->depth >= 0);
290     length = ctx->end - ctx->offset;
291     ctx->end = ctx->ends[ctx->depth--];
292     if((ctx->depth == -1) && (ctx->buffer))
293     {
294         MemoryCopy(ctx->buffer, ctx->buffer + ctx->offset, ctx->end - ctx->offset);
295     }
296     return length;
297 }
298 
299 
300 //***ASN1EndEncapsulation()
301 // This function puts a tag and length in the buffer. In this function, an embedded
302 // BIT_STRING is assumed to be a collection of octets. To indicate that all bits
303 // are used, a byte of zero is prepended. If a raw bit-string is needed, a new
304 // function like ASN1PushInteger() would be needed.
305 //  Return Type: INT16
306 //      > 0         number of octets in the encapsulation
307 //      == 0        failure
308 UINT16
ASN1EndEncapsulation(ASN1MarshalContext * ctx,BYTE tag)309 ASN1EndEncapsulation(
310     ASN1MarshalContext          *ctx,
311     BYTE                         tag
312 )
313 {
314     // only add a leading zero for an encapsulated BIT STRING
315     if (tag == ASN1_BITSTRING)
316         ASN1PushByte(ctx, 0);
317     ASN1PushTagAndLength(ctx, tag, ctx->end - ctx->offset);
318     return ASN1EndMarshalContext(ctx);
319 }
320 
321 //*** ASN1PushByte()
322 BOOL
ASN1PushByte(ASN1MarshalContext * ctx,BYTE b)323 ASN1PushByte(
324     ASN1MarshalContext          *ctx,
325     BYTE                         b
326 )
327 {
328     if(ctx->offset > 0)
329     {
330         ctx->offset -= 1;
331         if(ctx->buffer)
332             ctx->buffer[ctx->offset] = b;
333         return TRUE;
334     }
335     ctx->offset = -1;
336     return FALSE;
337 }
338 
339 //*** ASN1PushBytes()
340 // Push some raw bytes onto the buffer. 'count' cannot be zero.
341 //  Return Type: IN16
342 //      > 0             count bytes
343 //      == 0            failure unless count was zero
344 INT16
ASN1PushBytes(ASN1MarshalContext * ctx,INT16 count,const BYTE * buffer)345 ASN1PushBytes(
346     ASN1MarshalContext          *ctx,
347     INT16                        count,
348     const BYTE                  *buffer
349 )
350 {
351     // make sure that count is not negative which would mess up the math; and that
352     // if there is a count, there is a buffer
353     VERIFY((count >= 0) && ((buffer != NULL) || (count == 0)));
354     // back up the offset to determine where the new octets will get pushed
355     ctx->offset -= count;
356     // can't go negative
357     VERIFY(ctx->offset >= 0);
358     // if there are buffers, move the data, otherwise, assume that this is just a
359     // test.
360     if(count && buffer && ctx->buffer)
361         MemoryCopy(&ctx->buffer[ctx->offset], buffer, count);
362     return count;
363 Error:
364     ctx->offset = -1;
365     return 0;
366 }
367 
368 //*** ASN1PushNull()
369 //  Return Type: IN16
370 //      > 0             count bytes
371 //      == 0            failure unless count was zero
372 INT16
ASN1PushNull(ASN1MarshalContext * ctx)373 ASN1PushNull(
374     ASN1MarshalContext      *ctx
375 )
376 {
377     ASN1PushByte(ctx, 0);
378     ASN1PushByte(ctx, ASN1_NULL);
379     return (ctx->offset >= 0) ? 2 : 0;
380 }
381 
382 //*** ASN1PushLength()
383 // Push a length value. This will only handle length values that fit in an INT16.
384 //  Return Type: UINT16
385 //      > 0         number of bytes added
386 //      == 0        failure
387 INT16
ASN1PushLength(ASN1MarshalContext * ctx,INT16 len)388 ASN1PushLength(
389     ASN1MarshalContext          *ctx,
390     INT16                        len
391 )
392 {
393     UINT16                       start = ctx->offset;
394     VERIFY(len >= 0);
395     if(len <= 127)
396         ASN1PushByte(ctx, (BYTE)len);
397     else
398     {
399         ASN1PushByte(ctx, (BYTE)(len & 0xFF));
400         len >>= 8;
401         if(len == 0)
402             ASN1PushByte(ctx, 0x81);
403         else
404         {
405             ASN1PushByte(ctx, (BYTE)(len));
406             ASN1PushByte(ctx, 0x82);
407         }
408     }
409     goto Exit;
410 Error:
411     ctx->offset = -1;
412 Exit:
413     return (ctx->offset > 0) ? start - ctx->offset : 0;
414 }
415 
416 //*** ASN1PushTagAndLength()
417 //  Return Type: INT16
418 //      > 0         number of bytes added
419 //      == 0        failure
420 INT16
ASN1PushTagAndLength(ASN1MarshalContext * ctx,BYTE tag,INT16 length)421 ASN1PushTagAndLength(
422     ASN1MarshalContext          *ctx,
423     BYTE                         tag,
424     INT16                        length
425 )
426 {
427     INT16       bytes;
428     bytes = ASN1PushLength(ctx, length);
429     bytes += (INT16)ASN1PushByte(ctx, tag);
430     return (ctx->offset < 0) ? 0 : bytes;
431 }
432 
433 
434 //*** ASN1PushTaggedOctetString()
435 // This function will push a random octet string.
436 //  Return Type: INT16
437 //      > 0         number of bytes added
438 //      == 0        failure
439 INT16
ASN1PushTaggedOctetString(ASN1MarshalContext * ctx,INT16 size,const BYTE * string,BYTE tag)440 ASN1PushTaggedOctetString(
441     ASN1MarshalContext          *ctx,
442     INT16                        size,
443     const BYTE                  *string,
444     BYTE                         tag
445 )
446 {
447     ASN1PushBytes(ctx, size, string);
448     // PushTagAndLenght just tells how many octets it added so the total size of this
449     // element is the sum of those octets and input size.
450     size += ASN1PushTagAndLength(ctx, tag, size);
451     return size;
452 }
453 
454 //*** ASN1PushUINT()
455 // This function pushes an native-endian integer value. This just changes a
456 // native-endian integer into a big-endian byte string and calls ASN1PushInteger().
457 // That function will remove leading zeros and make sure that the number is positive.
458 //  Return Type: IN16
459 //      > 0             count bytes
460 //      == 0            failure unless count was zero
461 INT16
ASN1PushUINT(ASN1MarshalContext * ctx,UINT32 integer)462 ASN1PushUINT(
463     ASN1MarshalContext      *ctx,
464     UINT32                   integer
465 )
466 {
467     BYTE                    marshaled[4];
468     UINT32_TO_BYTE_ARRAY(integer, marshaled);
469     return ASN1PushInteger(ctx, 4, marshaled);
470 }
471 
472 //*** ASN1PushInteger
473 // Push a big-endian integer on the end of the buffer
474 //  Return Type: UINT16
475 //      > 0         the number of bytes marshaled for the integer
476 //      == 0        failure
477 INT16
ASN1PushInteger(ASN1MarshalContext * ctx,INT16 iLen,BYTE * integer)478 ASN1PushInteger(
479     ASN1MarshalContext  *ctx,           // IN/OUT: buffer context
480     INT16                iLen,          // IN: octets of the integer
481     BYTE                *integer        // IN: big-endian integer
482 )
483 {
484     // no leading 0's
485     while((*integer == 0) && (--iLen > 0))
486         integer++;
487     // Move the bytes to the buffer
488     ASN1PushBytes(ctx, iLen, integer);
489     // if needed, add a leading byte of 0 to make the number positive
490     if(*integer & 0x80)
491         iLen += (INT16)ASN1PushByte(ctx, 0);
492     // PushTagAndLenght just tells how many octets it added so the total size of this
493     // element is the sum of those octets and the adjusted input size.
494     iLen +=  ASN1PushTagAndLength(ctx, ASN1_INTEGER, iLen);
495     return iLen;
496 }
497 
498 //*** ASN1PushOID()
499 // This function is used to add an OID. An OID is 0x06 followed by a byte of size
500 // followed by size bytes. This is used to avoid having to do anything special in the
501 // definition of an OID.
502 //  Return Type: UINT16
503 //      > 0         the number of bytes marshaled for the integer
504 //      == 0        failure
505 INT16
ASN1PushOID(ASN1MarshalContext * ctx,const BYTE * OID)506 ASN1PushOID(
507     ASN1MarshalContext          *ctx,
508     const BYTE                  *OID
509 )
510 {
511     if((*OID == ASN1_OBJECT_IDENTIFIER) && ((OID[1] & 0x80) == 0))
512     {
513         return ASN1PushBytes(ctx, OID[1] + 2, OID);
514     }
515     ctx->offset = -1;
516     return 0;
517 }
518 
519 
520