]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_keychain/libDER/libDERUtils/printFields.c
Security-57031.1.35.tar.gz
[apple/security.git] / Security / libsecurity_keychain / libDER / libDERUtils / printFields.c
diff --git a/Security/libsecurity_keychain/libDER/libDERUtils/printFields.c b/Security/libsecurity_keychain/libDER/libDERUtils/printFields.c
new file mode 100644 (file)
index 0000000..51bcffe
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2005-2007,2011-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@
+ */
+
+
+/*
+ * printFeilds.h - print various DER objects
+ *
+ */
+
+#include <libDERUtils/printFields.h>
+#include <libDER/DER_Decode.h>
+#include <libDER/asn1Types.h>
+#include <libDER/DER_Keys.h>
+#include <libDERUtils/libDERUtils.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <stdio.h>
+
+static int indentLevel = 0;
+
+void doIndent(void)
+{
+       int i;
+       for (i = 0; i<indentLevel; i++) {
+               putchar(' ');
+       }
+} /* indent */
+
+void incrIndent(void)
+{
+       indentLevel += 3;
+}
+
+void decrIndent(void)
+{
+       indentLevel -= 3;
+}
+
+#define TO_PRINT_MAX   12
+
+void printHex(
+       DERItem *item)
+{
+       unsigned long dex;
+       unsigned long toPrint = item->length;
+       
+       printf("<%lu> ", item->length);
+       if(toPrint > TO_PRINT_MAX) {
+               toPrint = TO_PRINT_MAX;
+       }
+       for(dex=0; dex<toPrint; dex++) {
+               printf("%02x ", item->data[dex]);
+       }
+       if(item->length > TO_PRINT_MAX) {
+               printf("...");
+       }
+       printf("\n");
+}
+
+void printBitString(
+       DERItem *item)
+{
+       DERSize dex;
+       DERSize toPrint = item->length;
+       DERItem bitStringBytes;
+       DERByte numUnused;
+       DERReturn drtn;
+                       
+       drtn = DERParseBitString(item, &bitStringBytes, &numUnused);
+       if(drtn) {
+               DERPerror("DERParseBitString", drtn);
+               return;
+       }
+
+       printf("<%lu, %lu> ", (unsigned long)bitStringBytes.length, (unsigned long)numUnused);
+       toPrint = bitStringBytes.length;
+       if(toPrint > TO_PRINT_MAX) {
+               toPrint = TO_PRINT_MAX;
+       }
+       for(dex=0; dex<toPrint; dex++) {
+               printf("%02x ", bitStringBytes.data[dex]);
+       }
+       if(item->length > TO_PRINT_MAX) {
+               printf("...");
+       }
+       printf("\n");
+}
+
+void printString(
+       DERItem *item)
+{
+       unsigned dex;
+       char *cp = (char *)item->data;
+       printf("'");
+       for(dex=0; dex<item->length; dex++) {
+               putchar(*cp++);
+       }
+       printf("'\n");
+
+}
+
+#define COLON_COLUMN   20
+
+/*
+ * Print line header, with current indent, followed by specified label, followed
+ * by a ':' in column COLON_COLUMN, followed by one space. 
+ */
+void printHeader(
+       const char *label)
+{
+       size_t numPrinted;
+       
+       doIndent();
+       printf("%s", label);
+       numPrinted = indentLevel + strlen(label);
+       if(numPrinted < COLON_COLUMN) {
+               size_t numSpaces = COLON_COLUMN - numPrinted;
+               size_t dex;
+               for(dex=0; dex<numSpaces; dex++) {
+                       putchar(' ');
+               }
+       }
+       printf(": ");
+}
+
+void printItem(
+       const char *label,
+       ItemType itemType,
+       int verbose,
+       DERTag tag,         // maybe from decoding, maybe the real tag underlying
+                                               // an implicitly tagged item
+       DERItem *item)          // content 
+{
+       DERTag tagClass = tag & ASN1_CLASS_MASK;
+       DERTag tagNum = tag & ASN1_TAGNUM_MASK;
+       char printable = 0;
+       char *asnType = NULL;
+
+       printHeader(label);
+       
+       if((itemType == IT_Branch) && !verbose) {
+               printf("\n");
+               return;
+       }
+       switch(tagClass) {
+               case ASN1_UNIVERSAL:
+                       break;          // proceed with normal tags */
+               case ASN1_APPLICATION:
+                       printf("APPLICATION (tag %u) ", tagNum);
+                       printHex(item);
+                       return;
+               case ASN1_CONTEXT_SPECIFIC:
+                       printf("CONTEXT SPECIFIC (tag %u) ", tagNum);
+                       printHex(item);
+                       return;
+               case ASN1_PRIVATE:
+                       printf("PRIVATE (tag %u) ", tagNum);
+                       printHex(item);
+                       return;
+       }
+       switch(tagNum) {
+               case ASN1_BOOLEAN:
+                       asnType = "BOOLEAN";
+                       break;
+               case ASN1_INTEGER:
+                       asnType = "INTEGER";
+                       break;
+               case ASN1_BIT_STRING:
+                       /* special case here... */
+                       printf("BIT STRING ");
+                       printBitString(item);
+                       return;
+               case ASN1_OCTET_STRING:
+                       asnType = "OCTET STRING";
+                       break;
+               case ASN1_NULL:
+                       asnType = "NULL";
+                       break;
+               case ASN1_OBJECT_ID:
+                       asnType = "OID";
+                       break;
+               case ASN1_OBJECT_DESCRIPTOR:
+                       asnType = "OBJECT_DESCRIPTOR";
+                       break;
+               case ASN1_REAL:
+                       asnType = "REAL";
+                       break;
+               case ASN1_ENUMERATED:
+                       asnType = "ENUM";
+                       break;
+               case ASN1_EMBEDDED_PDV:
+                       asnType = "EMBEDDED_PDV";
+                       break;
+               case ASN1_UTF8_STRING:
+                       asnType = "UTF8 STRING";
+                       /* FIXME print these too */
+                       break;
+               case ASN1_SEQUENCE:
+                       asnType = "SEQ";
+                       break;
+               case ASN1_SET:
+                       asnType = "SET";
+                       break;
+               case ASN1_NUMERIC_STRING:
+                       asnType = "NUMERIC_STRING";
+                       break;
+               case ASN1_PRINTABLE_STRING:
+                       asnType = "PRINTABLE_STRING";
+                       printable = 1;
+                       break;
+               case ASN1_T61_STRING:
+                       asnType = "T61_STRING";
+                       printable = 1;
+                       break;
+               case ASN1_VIDEOTEX_STRING:
+                       asnType = "VIDEOTEX_STRING";
+                       printable = 1;
+                       break;
+               case ASN1_IA5_STRING:
+                       asnType = "IA5_STRING";
+                       printable = 1;
+                       break;
+               case ASN1_UTC_TIME:
+                       asnType = "UTC_TIME";
+                       printable = 1;
+                       break;
+               case ASN1_GENERALIZED_TIME:
+                       asnType = "GENERALIZED_TIME";
+                       printable = 1;
+                       break;
+               case ASN1_GRAPHIC_STRING:
+                       asnType = "GRAPHIC_STRING";
+                       break;
+               case ASN1_VISIBLE_STRING:
+                       asnType = "VISIBLE_STRING";
+                       break;
+               case ASN1_GENERAL_STRING:
+                       asnType = "GENERAL_STRING";
+                       break;
+               case ASN1_UNIVERSAL_STRING:
+                       asnType = "UNIVERSAL_STRING";
+                       break;
+               case ASN1_BMP_STRING:
+                       asnType = "BMP_STRING";
+                       break;
+               default:
+                       asnType = "[unknown]";
+                       break;
+       }
+       printf("%s ", asnType);
+       if(printable) {
+               printString(item);
+       }
+       else {
+               printHex(item);
+       }
+}
+
+void printAlgId(
+       const DERItem *content,
+       int verbose)
+{
+       DERReturn drtn;
+       DERAlgorithmId algId;
+       
+       drtn = DERParseSequenceContent(content,
+               DERNumAlgorithmIdItemSpecs, DERAlgorithmIdItemSpecs,
+               &algId, sizeof(algId));
+       if(drtn) {
+               DERPerror("DERParseSequenceContent(algId)", drtn);
+               return;
+       }
+       printItem("alg", IT_Leaf, verbose, ASN1_OBJECT_ID, &algId.oid);
+       if(algId.params.data) {
+               printItem("params", IT_Leaf, verbose, algId.params.data[0], &algId.params);
+       }
+}
+
+void printSubjPubKeyInfo(
+       const DERItem *content,
+       int verbose)
+{
+       DERReturn drtn;
+       DERSubjPubKeyInfo pubKeyInfo;
+       DERRSAPubKeyPKCS1 pkcs1Key;
+       DERItem bitStringContents;
+       DERByte numUnused;
+       
+       drtn = DERParseSequenceContent(content,
+               DERNumSubjPubKeyInfoItemSpecs, DERSubjPubKeyInfoItemSpecs,
+               &pubKeyInfo, sizeof(pubKeyInfo));
+       if(drtn) {
+               DERPerror("DERParseSequenceContent(pubKeyInfo)", drtn);
+               return;
+       }
+       printItem("algId", IT_Branch, verbose, ASN1_CONSTR_SEQUENCE, &pubKeyInfo.algId);
+       incrIndent();
+       printAlgId(&pubKeyInfo.algId, verbose);
+       decrIndent();
+
+       printItem("pubKey", IT_Branch, verbose, ASN1_BIT_STRING, &pubKeyInfo.pubKey);
+       
+       /* 
+        * The contents of that bit string are a PKCS1 format RSA key. 
+        */
+       drtn = DERParseBitString(&pubKeyInfo.pubKey, &bitStringContents, &numUnused);
+       if(drtn) {
+               DERPerror("DERParseBitString(pubKeyInfo.pubKey)", drtn);
+               decrIndent();
+               return;
+       }
+       drtn = DERParseSequence(&bitStringContents,
+               DERNumRSAPubKeyPKCS1ItemSpecs, DERRSAPubKeyPKCS1ItemSpecs,
+               &pkcs1Key, sizeof(pkcs1Key));
+       if(drtn) {
+               DERPerror("DERParseSequenceContent(pubKeyBits)", drtn);
+               decrIndent();
+               return;
+       }
+       incrIndent();
+       printItem("modulus", IT_Leaf, verbose, ASN1_INTEGER, &pkcs1Key.modulus);
+       printItem("pubExponent", IT_Leaf, verbose, ASN1_INTEGER, &pkcs1Key.pubExponent);
+       
+       decrIndent();
+}
+
+/* decode one item and print it */
+void decodePrintItem(
+       const char *label,
+       ItemType itemType,
+       int verbose,
+       DERItem *derItem)
+{
+       DERDecodedInfo decoded;
+       DERReturn drtn;
+       
+       drtn = DERDecodeItem(derItem, &decoded);
+       if(drtn) {
+               DERPerror("DERDecodeItem()", drtn);
+               return;
+       }
+       printItem(label, IT_Leaf, 0, decoded.tag, &decoded.content);
+}
+