EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp, long length) { STACK_OF(ASN1_TYPE) *inkey; const unsigned char *p; int keytype; p = *pp; /* Dirty trick: read in the ASN1 data into a STACK_OF(ASN1_TYPE): * by analyzing it we can determine the passed structure: this * assumes the input is surrounded by an ASN1 SEQUENCE. */ inkey = d2i_ASN1_SET_OF_ASN1_TYPE(NULL, &p, length, d2i_ASN1_TYPE, ASN1_TYPE_free, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); /* Since we only need to discern "traditional format" RSA and DSA * keys we can just count the elements. */ if(sk_ASN1_TYPE_num(inkey) == 6) keytype = EVP_PKEY_DSA; else if (sk_ASN1_TYPE_num(inkey) == 4) keytype = EVP_PKEY_EC; else keytype = EVP_PKEY_RSA; sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free); return d2i_PrivateKey(keytype, a, pp, length); }
char* CERTIFICATE_FILE_CLASS::derDecode(unsigned char **buf_ptrptr, long length) // DESCRIPTION : Determine the type of the DER data and decode it. // PRECONDITIONS : // POSTCONDITIONS : // EXCEPTIONS : // NOTES : Returns a pointer to a new'd DVT_STATUS, which must be deleted by the caller //<<=========================================================================== { DVT_STATUS status = MSG_ERROR; unsigned char *p; STACK_OF(ASN1_TYPE) *inkey_ptr = NULL; EVP_PKEY *pkey_ptr = NULL; X509 *cert_ptr = NULL; int count = 0; // try to determine the contents of the file [this is adapted from d2i_AutoPrivateKey()] p = *buf_ptrptr; inkey_ptr = d2i_ASN1_SET_OF_ASN1_TYPE(NULL, &p, length, d2i_ASN1_TYPE, ASN1_TYPE_free, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); if (inkey_ptr == NULL) { // probably not a DER file status = MSG_NO_VALUE; goto end; } switch (sk_ASN1_TYPE_num(inkey_ptr)) { case 3: // certificate file p = *buf_ptrptr; cert_ptr = (X509*)ASN1_item_d2i(NULL, &p, length, ASN1_ITEM_rptr(X509)); if (cert_ptr == NULL) { openSslM_ptr->printError(loggerM_ptr, LOG_ERROR, "decoding certificate in DER file"); status = MSG_ERROR; goto end; } else { // save the certificate if (!push(cert_ptr)) { status = MSG_ERROR; goto end; } count++; } break; case 6: // DSA private key file p = *buf_ptrptr; pkey_ptr = d2i_PrivateKey(EVP_PKEY_DSA, NULL, &p, length); if (pkey_ptr == NULL) { openSslM_ptr->printError(loggerM_ptr, LOG_ERROR, "decoding private key in DER file"); status = MSG_ERROR; goto end; } else { // save the private key if (!push(pkey_ptr)) { status = MSG_ERROR; goto end; } count++; } break; case 9: // RSA private key file p = *buf_ptrptr; pkey_ptr = d2i_PrivateKey(EVP_PKEY_RSA, NULL, &p, length); if (pkey_ptr == NULL) { openSslM_ptr->printError(loggerM_ptr, LOG_ERROR, "decoding private key in DER file"); status = MSG_ERROR; goto end; } else { // save the private key if (!push(pkey_ptr)) { status = MSG_ERROR; goto end; } count++; } break; default: // unknown data status = MSG_NO_VALUE; goto end; } if (count == 0) { status = MSG_NO_VALUE; } else { status = MSG_OK; } end: if (inkey_ptr != NULL) sk_ASN1_TYPE_pop_free(inkey_ptr, ASN1_TYPE_free); if (pkey_ptr != NULL) EVP_PKEY_free(pkey_ptr); if (cert_ptr != NULL) X509_free(cert_ptr); return (char*)(new DVT_STATUS(status)); }