]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_keychain/libDER/Tests/DER_Ticket.c
Security-57031.1.35.tar.gz
[apple/security.git] / Security / libsecurity_keychain / libDER / Tests / DER_Ticket.c
diff --git a/Security/libsecurity_keychain/libDER/Tests/DER_Ticket.c b/Security/libsecurity_keychain/libDER/Tests/DER_Ticket.c
new file mode 100644 (file)
index 0000000..c5be481
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2009,2012,2014 Apple Inc. All Rights Reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+
+#include "DER_Ticket.h"
+
+#include <libDER/asn1Types.h>
+#include <libDER/DER_Decode.h>
+#include <libDER/DER_Encode.h>
+#include <libDER/DER_Keys.h>
+
+/* Application Processor Ticket */
+const DERItemSpec DERApTicketItemSpecs[] =
+{
+       { DER_OFFSET(DERApTicket, signatureAlgorithm),
+                       ASN1_CONSTR_SEQUENCE,
+                       DER_DEC_NO_OPTS | DER_ENC_WRITE_DER },
+       { DER_OFFSET(DERApTicket, body),
+                       ASN1_CONSTR_SET,
+                       DER_DEC_NO_OPTS | DER_DEC_SAVE_DER | DER_ENC_WRITE_DER },
+       { DER_OFFSET(DERApTicket, signature),
+                       ASN1_OCTET_STRING,
+                       DER_DEC_NO_OPTS },
+       { DER_OFFSET(DERApTicket, certificates),
+                       ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1,
+                       DER_DEC_NO_OPTS | DER_ENC_WRITE_DER }
+};
+const DERSize DERNumApTicketItemSpecs =
+       sizeof(DERApTicketItemSpecs) / sizeof(DERItemSpec);
+
+/* Baseband Ticket */
+const DERItemSpec DERBbTicketItemSpecs[] =
+{
+       { DER_OFFSET(DERBbTicket, signatureAlgorithm),
+                       ASN1_CONSTR_SEQUENCE,
+                       DER_DEC_NO_OPTS | DER_ENC_WRITE_DER },
+       { DER_OFFSET(DERBbTicket, body),
+                       ASN1_CONSTR_SET,
+                       DER_DEC_NO_OPTS | DER_DEC_SAVE_DER | DER_ENC_WRITE_DER },
+       { DER_OFFSET(DERBbTicket, signature),
+                       ASN1_OCTET_STRING,
+                       DER_DEC_NO_OPTS },
+       { DER_OFFSET(DERBbTicket, gpuk),
+                       ASN1_CONTEXT_SPECIFIC | 2,
+                       DER_DEC_NO_OPTS }
+};
+const DERSize DERNumBbTicketItemSpecs =
+       sizeof(DERBbTicketItemSpecs) / sizeof(DERItemSpec);
+
+#if 0
+/* We need to verify this value and use it here. */
+const DERByte rsaWithSha1Algorithm[] = {
+    0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05
+};
+#endif
+
+#ifdef FAST_SET_LOOKUP
+/* Iterates over all the tags in the set to build an index returned in
+   derSet. */
+DERReturn DERDecodeSetContentInit(
+       const DERItem   *content,                       /* data to decode */
+       DERSet          *derSet)            /* IN/OUT, to use in DERDecodeSetTag */
+{
+    DERReturn drtn;
+    DERSequence derSeq;
+    memset(derSet->byTag, 0, derSet->capacity);
+    drtn = DERDecodeSeqContentInit(content, &derSeq);
+    if (drtn == DR_Success) {
+        DERDecodedInfo element;
+        while ((drtn = DERDecodeSeqNext(&derSeq, &element)) == DR_Success) {
+            if (element.tag >= derSet->capacity) return DR_UnexpectedTag;
+            derSet->byTag[element.tag] = element.content.data;
+        }
+        if (drtn == DR_EndOfSequence) drtn = DR_Success;
+    }
+    derSet->end = content->data + content->length;
+
+    return drtn;
+}
+
+DERReturn DERDecodeSetTag(
+       DERSet          *derSet,                /* data to decode */
+       DERTag                  tag,                    /* tag in sequence/set we are looking for. */
+       DERItem         *content)               /* RETURNED */
+{
+    DERReturn drtn;
+    DERTag tagNumber = tag & ASN1_TAGNUM_MASK;
+    if (tagNumber > derSet->capacity)
+        return DR_UnexpectedTag;
+    DERByte *start = derSet->byTag[tagNumber];
+    if (!start) return DR_UnexpectedTag;
+    DERItem derItem = { .data = start, .length = derSet->end - start };
+    DERDecodedInfo element;
+    drtn = DERDecodeItem(&derItem, &element);
+    if (drtn) return drtn;
+    if (tag != element.tag) return DR_UnexpectedTag;
+    *content = element.content;
+
+    return drtn;
+}
+#endif /* FAST_SET_LOOKUP */
+
+/* Returns the item with tag from the sequence or set pointed to by der.
+   result DR_EndOfSequence if the tag was not found. */
+DERReturn DERSetDecodeItemWithTag(
+       const DERItem   *der,                   /* data to decode */
+       DERTag                  tag,                    /* tag in sequence/set we are looking for. */
+       DERItem         *content)               /* RETURNED */
+{
+    DERReturn drtn;
+    DERSequence derSeq;
+    DERTag topTag;
+    drtn = DERDecodeSeqInit(der, &topTag, &derSeq);
+    if (drtn == DR_Success) {
+        DERDecodedInfo info;
+        while ((drtn = DERDecodeSeqNext(&derSeq, &info)) == DR_Success) {
+            if (info.tag == tag) {
+                *content = info.content;
+                return DR_Success;
+            }
+        }
+    }
+
+    return drtn;
+}
+
+DERReturn DERDecodeApTicket(
+       const DERItem   *contents,
+       DERApTicket             *ticket,            /* RETURNED */
+       DERSize                 *numUsedBytes)      /* RETURNED */
+{
+    DERReturn drtn;
+    DERDecodedInfo decodedTicket;
+    drtn = DERDecodeItem(contents, &decodedTicket);
+    if (drtn != DR_Success) goto badTicket;
+    drtn = DERParseSequenceContent(&decodedTicket.content,
+        DERNumApTicketItemSpecs, DERApTicketItemSpecs, ticket, 0);
+    if (drtn != DR_Success) goto badTicket;
+
+    /* Decode the algorithm sequence. */
+    DERAlgorithmId algorithm = {};
+    drtn = DERParseSequenceContent(&ticket->signatureAlgorithm,
+        DERNumAlgorithmIdItemSpecs, DERAlgorithmIdItemSpecs, &algorithm, 0);
+    if (drtn != DR_Success) goto badTicket;
+    /* TODO Check algorithm oid and ensure there are no params.
+       Alternatively replace the code above with a simple memcmp with
+       an already ASN.1 encoded algorithm parms block. */
+
+badTicket:
+    *numUsedBytes = decodedTicket.content.length +
+        decodedTicket.content.data - contents->data;
+
+    return drtn;
+}
+
+DERReturn DERDecodeBbTicket(
+       const DERItem   *contents,
+       DERBbTicket             *ticket,            /* RETURNED */
+       DERSize                 *numUsedBytes)      /* RETURNED */
+{
+    DERReturn drtn;
+    DERDecodedInfo decodedTicket;
+    drtn = DERDecodeItem(contents, &decodedTicket);
+    if (drtn != DR_Success) goto badTicket;
+    drtn = DERParseSequenceContent(&decodedTicket.content,
+        DERNumBbTicketItemSpecs, DERBbTicketItemSpecs, ticket, 0);
+    if (drtn != DR_Success) goto badTicket;
+
+    /* Decode the algorithm sequence. */
+    DERAlgorithmId algorithm = {};
+    drtn = DERParseSequenceContent(&ticket->signatureAlgorithm,
+        DERNumAlgorithmIdItemSpecs, DERAlgorithmIdItemSpecs, &algorithm, 0);
+    if (drtn != DR_Success) goto badTicket;
+    /* TODO Check algorithm oid and ensure there are no params.
+       Alternatively replace the code above with a simple memcmp with
+       an already ASN.1 encoded algorithm parms block. */
+
+badTicket:
+    *numUsedBytes = decodedTicket.content.length +
+        decodedTicket.content.data - contents->data;
+
+    return drtn;
+}