EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **a, const unsigned char **pp, long length) { EVP_PKEY *ret; if ((a == NULL) || (*a == NULL)) { if ((ret = EVP_PKEY_new()) == NULL) { ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_EVP_LIB); return (NULL); } } else ret = *a; if (!EVP_PKEY_set_type(ret, type)) { ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_EVP_LIB); goto err; } switch (EVP_PKEY_id(ret)) { #ifndef OPENSSL_NO_RSA case EVP_PKEY_RSA: if ((ret->pkey.rsa = d2i_RSAPublicKey(NULL, pp, length)) == NULL) { ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB); goto err; } break; #endif #ifndef OPENSSL_NO_DSA case EVP_PKEY_DSA: /* TMP UGLY CAST */ if (!d2i_DSAPublicKey(&ret->pkey.dsa, pp, length)) { ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB); goto err; } break; #endif #ifndef OPENSSL_NO_EC case EVP_PKEY_EC: if (!o2i_ECPublicKey(&ret->pkey.ec, pp, length)) { ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB); goto err; } break; #endif default: ASN1err(ASN1_F_D2I_PUBLICKEY, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE); goto err; /* break; */ } if (a != NULL) (*a) = ret; return (ret); err: if (a == NULL || *a != ret) EVP_PKEY_free(ret); return (NULL); }
/* * Decode a string to a key. Return 0 on success. */ int kn_decode_key(struct keynote_deckey *dc, char *key, int keytype) { void *kk = NULL; X509 *px509Cert; EVP_PKEY *pPublicKey; unsigned char *ptr = NULL, *decoded = NULL; int encoding, internalencoding; long len = 0; keynote_errno = 0; if (keytype == KEYNOTE_PRIVATE_KEY) dc->dec_algorithm = keynote_get_private_key_algorithm(key, &encoding, &internalencoding); else dc->dec_algorithm = keynote_get_key_algorithm(key, &encoding, &internalencoding); if (dc->dec_algorithm == KEYNOTE_ALGORITHM_NONE) { if ((dc->dec_key = strdup(key)) == NULL) { keynote_errno = ERROR_MEMORY; return -1; } return 0; } key = strchr(key, ':'); /* Move forward, to the Encoding. We're guaranteed * to have a ':' character, since this is a key */ key++; /* Remove ASCII encoding */ switch (encoding) { case ENCODING_NONE: break; case ENCODING_HEX: len = strlen(key) / 2; if (kn_decode_hex(key, (char **) &decoded) != 0) return -1; ptr = decoded; break; case ENCODING_BASE64: len = strlen(key); if (len % 4) /* Base64 encoding must be a multiple of 4 */ { keynote_errno = ERROR_SYNTAX; return -1; } len = 3 * (len / 4); decoded = calloc(len, sizeof(unsigned char)); ptr = decoded; if (decoded == NULL) { keynote_errno = ERROR_MEMORY; return -1; } if ((len = kn_decode_base64(key, decoded, len)) == -1) return -1; break; case ENCODING_NATIVE: decoded = strdup(key); if (decoded == NULL) { keynote_errno = ERROR_MEMORY; return -1; } len = strlen(key); ptr = decoded; break; default: keynote_errno = ERROR_SYNTAX; return -1; } /* DSA-HEX */ if ((dc->dec_algorithm == KEYNOTE_ALGORITHM_DSA) && (internalencoding == INTERNAL_ENC_ASN1)) { dc->dec_key = DSA_new(); if (dc->dec_key == NULL) { keynote_errno = ERROR_MEMORY; return -1; } kk = dc->dec_key; if (keytype == KEYNOTE_PRIVATE_KEY) { if (d2i_DSAPrivateKey((DSA **) &kk,(const unsigned char **) &decoded, len) == NULL) { free(ptr); DSA_free(kk); keynote_errno = ERROR_SYNTAX; /* Could be a memory error */ return -1; } } else { if (d2i_DSAPublicKey((DSA **) &kk, (const unsigned char **) &decoded, len) == NULL) { free(ptr); DSA_free(kk); keynote_errno = ERROR_SYNTAX; /* Could be a memory error */ return -1; } } free(ptr); return 0; } /* RSA-PKCS1-HEX */ if ((dc->dec_algorithm == KEYNOTE_ALGORITHM_RSA) && (internalencoding == INTERNAL_ENC_PKCS1)) { dc->dec_key = RSA_new(); if (dc->dec_key == NULL) { keynote_errno = ERROR_MEMORY; return -1; } kk = dc->dec_key; if (keytype == KEYNOTE_PRIVATE_KEY) { if (d2i_RSAPrivateKey((RSA **) &kk, (const unsigned char **) &decoded, len) == NULL) { free(ptr); RSA_free(kk); keynote_errno = ERROR_SYNTAX; /* Could be a memory error */ return -1; } if (RSA_blinding_on((RSA *) kk, NULL) != 1) { free(ptr); RSA_free(kk); keynote_errno = ERROR_MEMORY; return -1; } } else { if (d2i_RSAPublicKey((RSA **) &kk, (const unsigned char **) &decoded, len) == NULL) { free(ptr); RSA_free(kk); keynote_errno = ERROR_SYNTAX; /* Could be a memory error */ return -1; } } free(ptr); return 0; } /* X509 Cert */ if ((dc->dec_algorithm == KEYNOTE_ALGORITHM_X509) && (internalencoding == INTERNAL_ENC_ASN1) && (keytype == KEYNOTE_PUBLIC_KEY)) { if ((px509Cert = X509_new()) == NULL) { free(ptr); keynote_errno = ERROR_MEMORY; return -1; } if(d2i_X509(&px509Cert, (const unsigned char **)&decoded, len) == NULL) { free(ptr); X509_free(px509Cert); keynote_errno = ERROR_SYNTAX; return -1; } if ((pPublicKey = X509_get_pubkey(px509Cert)) == NULL) { free(ptr); X509_free(px509Cert); keynote_errno = ERROR_SYNTAX; return -1; } /* RSA-specific */ dc->dec_key = pPublicKey->pkey.rsa; free(ptr); return 0; } /* BINARY keys */ if ((dc->dec_algorithm == KEYNOTE_ALGORITHM_BINARY) && (internalencoding == INTERNAL_ENC_NONE)) { dc->dec_key = calloc(1, sizeof(struct keynote_binary)); if (dc->dec_key == NULL) { keynote_errno = ERROR_MEMORY; return -1; } ((struct keynote_binary *) dc->dec_key)->bn_key = decoded; ((struct keynote_binary *) dc->dec_key)->bn_len = len; return RESULT_TRUE; } /* Add support for more algorithms here */ free(ptr); /* This shouldn't ever be reached really */ keynote_errno = ERROR_SYNTAX; return -1; }