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;
}