1/* 2 * Copyright (c) 2005-2007,2011-2012,2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25/* 26 * printFeilds.h - print various DER objects 27 * 28 */ 29 30#include <libDERUtils/printFields.h> 31#include <libDER/DER_Decode.h> 32#include <libDER/asn1Types.h> 33#include <libDER/DER_Keys.h> 34#include <libDERUtils/libDERUtils.h> 35#include <stdlib.h> 36#include <strings.h> 37#include <stdio.h> 38 39static int indentLevel = 0; 40 41void doIndent(void) 42{ 43 int i; 44 for (i = 0; i<indentLevel; i++) { 45 putchar(' '); 46 } 47} /* indent */ 48 49void incrIndent(void) 50{ 51 indentLevel += 3; 52} 53 54void decrIndent(void) 55{ 56 indentLevel -= 3; 57} 58 59#define TO_PRINT_MAX 12 60 61void printHex( 62 DERItem *item) 63{ 64 unsigned long dex; 65 unsigned long toPrint = item->length; 66 67 printf("<%lu> ", item->length); 68 if(toPrint > TO_PRINT_MAX) { 69 toPrint = TO_PRINT_MAX; 70 } 71 for(dex=0; dex<toPrint; dex++) { 72 printf("%02x ", item->data[dex]); 73 } 74 if(item->length > TO_PRINT_MAX) { 75 printf("..."); 76 } 77 printf("\n"); 78} 79 80void printBitString( 81 DERItem *item) 82{ 83 DERSize dex; 84 DERSize toPrint = item->length; 85 DERItem bitStringBytes; 86 DERByte numUnused; 87 DERReturn drtn; 88 89 drtn = DERParseBitString(item, &bitStringBytes, &numUnused); 90 if(drtn) { 91 DERPerror("DERParseBitString", drtn); 92 return; 93 } 94 95 printf("<%lu, %lu> ", (unsigned long)bitStringBytes.length, (unsigned long)numUnused); 96 toPrint = bitStringBytes.length; 97 if(toPrint > TO_PRINT_MAX) { 98 toPrint = TO_PRINT_MAX; 99 } 100 for(dex=0; dex<toPrint; dex++) { 101 printf("%02x ", bitStringBytes.data[dex]); 102 } 103 if(item->length > TO_PRINT_MAX) { 104 printf("..."); 105 } 106 printf("\n"); 107} 108 109void printString( 110 DERItem *item) 111{ 112 unsigned dex; 113 char *cp = (char *)item->data; 114 printf("'"); 115 for(dex=0; dex<item->length; dex++) { 116 putchar(*cp++); 117 } 118 printf("'\n"); 119 120} 121 122#define COLON_COLUMN 20 123 124/* 125 * Print line header, with current indent, followed by specified label, followed 126 * by a ':' in column COLON_COLUMN, followed by one space. 127 */ 128void printHeader( 129 const char *label) 130{ 131 size_t numPrinted; 132 133 doIndent(); 134 printf("%s", label); 135 numPrinted = indentLevel + strlen(label); 136 if(numPrinted < COLON_COLUMN) { 137 size_t numSpaces = COLON_COLUMN - numPrinted; 138 size_t dex; 139 for(dex=0; dex<numSpaces; dex++) { 140 putchar(' '); 141 } 142 } 143 printf(": "); 144} 145 146void printItem( 147 const char *label, 148 ItemType itemType, 149 int verbose, 150 DERTag tag, // maybe from decoding, maybe the real tag underlying 151 // an implicitly tagged item 152 DERItem *item) // content 153{ 154 DERTag tagClass = tag & ASN1_CLASS_MASK; 155 DERTag tagNum = tag & ASN1_TAGNUM_MASK; 156 char printable = 0; 157 char *asnType = NULL; 158 159 printHeader(label); 160 161 if((itemType == IT_Branch) && !verbose) { 162 printf("\n"); 163 return; 164 } 165 switch(tagClass) { 166 case ASN1_UNIVERSAL: 167 break; // proceed with normal tags */ 168 case ASN1_APPLICATION: 169 printf("APPLICATION (tag %u) ", tagNum); 170 printHex(item); 171 return; 172 case ASN1_CONTEXT_SPECIFIC: 173 printf("CONTEXT SPECIFIC (tag %u) ", tagNum); 174 printHex(item); 175 return; 176 case ASN1_PRIVATE: 177 printf("PRIVATE (tag %u) ", tagNum); 178 printHex(item); 179 return; 180 } 181 switch(tagNum) { 182 case ASN1_BOOLEAN: 183 asnType = "BOOLEAN"; 184 break; 185 case ASN1_INTEGER: 186 asnType = "INTEGER"; 187 break; 188 case ASN1_BIT_STRING: 189 /* special case here... */ 190 printf("BIT STRING "); 191 printBitString(item); 192 return; 193 case ASN1_OCTET_STRING: 194 asnType = "OCTET STRING"; 195 break; 196 case ASN1_NULL: 197 asnType = "NULL"; 198 break; 199 case ASN1_OBJECT_ID: 200 asnType = "OID"; 201 break; 202 case ASN1_OBJECT_DESCRIPTOR: 203 asnType = "OBJECT_DESCRIPTOR"; 204 break; 205 case ASN1_REAL: 206 asnType = "REAL"; 207 break; 208 case ASN1_ENUMERATED: 209 asnType = "ENUM"; 210 break; 211 case ASN1_EMBEDDED_PDV: 212 asnType = "EMBEDDED_PDV"; 213 break; 214 case ASN1_UTF8_STRING: 215 asnType = "UTF8 STRING"; 216 /* FIXME print these too */ 217 break; 218 case ASN1_SEQUENCE: 219 asnType = "SEQ"; 220 break; 221 case ASN1_SET: 222 asnType = "SET"; 223 break; 224 case ASN1_NUMERIC_STRING: 225 asnType = "NUMERIC_STRING"; 226 break; 227 case ASN1_PRINTABLE_STRING: 228 asnType = "PRINTABLE_STRING"; 229 printable = 1; 230 break; 231 case ASN1_T61_STRING: 232 asnType = "T61_STRING"; 233 printable = 1; 234 break; 235 case ASN1_VIDEOTEX_STRING: 236 asnType = "VIDEOTEX_STRING"; 237 printable = 1; 238 break; 239 case ASN1_IA5_STRING: 240 asnType = "IA5_STRING"; 241 printable = 1; 242 break; 243 case ASN1_UTC_TIME: 244 asnType = "UTC_TIME"; 245 printable = 1; 246 break; 247 case ASN1_GENERALIZED_TIME: 248 asnType = "GENERALIZED_TIME"; 249 printable = 1; 250 break; 251 case ASN1_GRAPHIC_STRING: 252 asnType = "GRAPHIC_STRING"; 253 break; 254 case ASN1_VISIBLE_STRING: 255 asnType = "VISIBLE_STRING"; 256 break; 257 case ASN1_GENERAL_STRING: 258 asnType = "GENERAL_STRING"; 259 break; 260 case ASN1_UNIVERSAL_STRING: 261 asnType = "UNIVERSAL_STRING"; 262 break; 263 case ASN1_BMP_STRING: 264 asnType = "BMP_STRING"; 265 break; 266 default: 267 asnType = "[unknown]"; 268 break; 269 } 270 printf("%s ", asnType); 271 if(printable) { 272 printString(item); 273 } 274 else { 275 printHex(item); 276 } 277} 278 279void printAlgId( 280 const DERItem *content, 281 int verbose) 282{ 283 DERReturn drtn; 284 DERAlgorithmId algId; 285 286 drtn = DERParseSequenceContent(content, 287 DERNumAlgorithmIdItemSpecs, DERAlgorithmIdItemSpecs, 288 &algId, sizeof(algId)); 289 if(drtn) { 290 DERPerror("DERParseSequenceContent(algId)", drtn); 291 return; 292 } 293 printItem("alg", IT_Leaf, verbose, ASN1_OBJECT_ID, &algId.oid); 294 if(algId.params.data) { 295 printItem("params", IT_Leaf, verbose, algId.params.data[0], &algId.params); 296 } 297} 298 299void printSubjPubKeyInfo( 300 const DERItem *content, 301 int verbose) 302{ 303 DERReturn drtn; 304 DERSubjPubKeyInfo pubKeyInfo; 305 DERRSAPubKeyPKCS1 pkcs1Key; 306 DERItem bitStringContents; 307 DERByte numUnused; 308 309 drtn = DERParseSequenceContent(content, 310 DERNumSubjPubKeyInfoItemSpecs, DERSubjPubKeyInfoItemSpecs, 311 &pubKeyInfo, sizeof(pubKeyInfo)); 312 if(drtn) { 313 DERPerror("DERParseSequenceContent(pubKeyInfo)", drtn); 314 return; 315 } 316 printItem("algId", IT_Branch, verbose, ASN1_CONSTR_SEQUENCE, &pubKeyInfo.algId); 317 incrIndent(); 318 printAlgId(&pubKeyInfo.algId, verbose); 319 decrIndent(); 320 321 printItem("pubKey", IT_Branch, verbose, ASN1_BIT_STRING, &pubKeyInfo.pubKey); 322 323 /* 324 * The contents of that bit string are a PKCS1 format RSA key. 325 */ 326 drtn = DERParseBitString(&pubKeyInfo.pubKey, &bitStringContents, &numUnused); 327 if(drtn) { 328 DERPerror("DERParseBitString(pubKeyInfo.pubKey)", drtn); 329 decrIndent(); 330 return; 331 } 332 drtn = DERParseSequence(&bitStringContents, 333 DERNumRSAPubKeyPKCS1ItemSpecs, DERRSAPubKeyPKCS1ItemSpecs, 334 &pkcs1Key, sizeof(pkcs1Key)); 335 if(drtn) { 336 DERPerror("DERParseSequenceContent(pubKeyBits)", drtn); 337 decrIndent(); 338 return; 339 } 340 incrIndent(); 341 printItem("modulus", IT_Leaf, verbose, ASN1_INTEGER, &pkcs1Key.modulus); 342 printItem("pubExponent", IT_Leaf, verbose, ASN1_INTEGER, &pkcs1Key.pubExponent); 343 344 decrIndent(); 345} 346 347/* decode one item and print it */ 348void decodePrintItem( 349 const char *label, 350 ItemType itemType, 351 int verbose, 352 DERItem *derItem) 353{ 354 DERDecodedInfo decoded; 355 DERReturn drtn; 356 357 drtn = DERDecodeItem(derItem, &decoded); 358 if(drtn) { 359 DERPerror("DERDecodeItem()", drtn); 360 return; 361 } 362 printItem(label, IT_Leaf, 0, decoded.tag, &decoded.content); 363} 364 365