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 printSubjPubKeyInfo( const DERItem *content, int verbose) { DERReturn drtn; DERSubjPubKeyInfo pubKeyInfo; DERRSAPubKeyPKCS1 pkcs1Key; DERItem bitStringContents; DERByte numUnused; drtn = DERParseSequence(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(); }
/* * Given a SSLCertificate cert, obtain its public key as a SSLPubKey. * Caller must sslFreePubKey and free the SSLPubKey itself. */ OSStatus sslPubKeyFromCert( SSLContext *ctx, const SSLCertificate *cert, SSLPubKey **pubKey) // RETURNED { DERItem der; DERSignedCertCrl signedCert; DERTBSCert tbsCert; DERSubjPubKeyInfo pubKeyInfo; DERByte numUnused; DERItem pubKeyPkcs1; SSLPubKey *key; DERReturn drtn; RSAStatus rsaStatus; assert(cert); assert(pubKey != NULL); der.data = cert->derCert.data; der.length = cert->derCert.length; /* top level decode */ drtn = DERParseSequence(&der, DERNumSignedCertCrlItemSpecs, DERSignedCertCrlItemSpecs, &signedCert, sizeof(signedCert)); if(drtn) return errSSLBadCert; /* decode the TBSCert - it was saved in full DER form */ drtn = DERParseSequence(&signedCert.tbs, DERNumTBSCertItemSpecs, DERTBSCertItemSpecs, &tbsCert, sizeof(tbsCert)); if(drtn) return errSSLBadCert; /* sequence we're given: encoded DERSubjPubKeyInfo */ drtn = DERParseSequenceContent(&tbsCert.subjectPubKey, DERNumSubjPubKeyInfoItemSpecs, DERSubjPubKeyInfoItemSpecs, &pubKeyInfo, sizeof(pubKeyInfo)); if(drtn) return errSSLBadCert; /* @@@ verify that this is an RSA key by decoding the AlgId */ /* * The contents of pubKeyInfo.pubKey is a bit string whose contents * are a PKCS1 format RSA key. */ drtn = DERParseBitString(&pubKeyInfo.pubKey, &pubKeyPkcs1, &numUnused); if(drtn) return errSSLBadCert; #if TARGET_OS_IOS /* Now we have the public key in pkcs1 format. Let's make a public key object out of it. */ key = sslMalloc(sizeof(*key)); rsaStatus = RSA_DecodePubKey(pubKeyPkcs1.data, pubKeyPkcs1.length, &key->rsaKey); if (rsaStatus) { sslFree(key); } #else SecKeyRef rsaPubKeyRef = SecKeyCreateRSAPublicKey(NULL, pubKeyPkcs1.data, pubKeyPkcs1.length, kSecKeyEncodingRSAPublicParams); rsaStatus = (rsaPubKeyRef) ? 0 : 1; key = (SSLPubKey*)rsaPubKeyRef; #endif if (rsaStatus) { return rsaStatusToSSL(rsaStatus); } *pubKey = key; return noErr; }