Commit a09003ea authored by Richard Levitte's avatar Richard Levitte
Browse files

STORE 'file' scheme loader: add support for the PKCS#12 container

parent e61ec2d9
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -750,6 +750,7 @@ OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT:117:ossl_store_register_loader_int
OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT:116:\
	ossl_store_unregister_loader_int
OSSL_STORE_F_TRY_DECODE_PARAMS:121:try_decode_params
OSSL_STORE_F_TRY_DECODE_PKCS12:122:try_decode_PKCS12
PEM_F_B2I_DSS:127:b2i_dss
PEM_F_B2I_PVK_BIO:128:b2i_PVK_bio
PEM_F_B2I_RSA:129:b2i_rsa
@@ -1977,6 +1978,7 @@ OCSP_R_UNKNOWN_MESSAGE_DIGEST:119:unknown message digest
OCSP_R_UNKNOWN_NID:120:unknown nid
OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE:129:unsupported requestorname type
OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE:107:ambiguous content type
OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC:113:error verifying pkcs12 mac
OSSL_STORE_R_INVALID_SCHEME:106:invalid scheme
OSSL_STORE_R_IS_NOT_A:112:is not a
OSSL_STORE_R_NOT_A_CERTIFICATE:100:not a certificate
@@ -1984,6 +1986,7 @@ OSSL_STORE_R_NOT_A_CRL:101:not a crl
OSSL_STORE_R_NOT_A_KEY:102:not a key
OSSL_STORE_R_NOT_A_NAME:103:not a name
OSSL_STORE_R_NOT_PARAMETERS:104:not parameters
OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR:114:passphrase callback error
OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE:108:path must be absolute
OSSL_STORE_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED:109:\
	ui process interrupted or cancelled
+116 −0
Original line number Diff line number Diff line
@@ -157,6 +157,121 @@ typedef struct file_handler_st {
    int repeatable;
} FILE_HANDLER;

static OSSL_STORE_INFO *try_decode_PKCS12(const char *pem_name,
                                          const char *pem_header,
                                          const unsigned char *blob,
                                          size_t len, void **pctx,
                                          const UI_METHOD *ui_method,
                                          void *ui_data)
{
    OSSL_STORE_INFO *store_info = NULL;
    STACK_OF(OSSL_STORE_INFO) *ctx = *pctx;

    if (ctx == NULL) {
        /* Initial parsing */
        PKCS12 *p12;
        int ok = 0;

        if (pem_name != NULL)
            /* No match, there is no PEM PKCS12 tag */
            return NULL;

        if ((p12 = d2i_PKCS12(NULL, &blob, len)) != NULL) {
            char *pass = NULL;
            char tpass[PEM_BUFSIZE];
            EVP_PKEY *pkey = NULL;
            X509 *cert = NULL;
            STACK_OF(X509) *chain = NULL;

            if (PKCS12_verify_mac(p12, "", 0)
                || PKCS12_verify_mac(p12, NULL, 0)) {
                pass = "";
            } else {
                if ((pass = file_get_pass(ui_method, tpass, PEM_BUFSIZE,
                                          "PKCS12 import password",
                                          ui_data)) == NULL) {
                    OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS12,
                                  OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR);
                    goto p12_end;
                }
                if (!PKCS12_verify_mac(p12, pass, strlen(pass))) {
                    OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS12,
                                  OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC);
                    goto p12_end;
                }
            }

            if (PKCS12_parse(p12, pass, &pkey, &cert, &chain)) {
                OSSL_STORE_INFO *si_pkey = NULL;
                OSSL_STORE_INFO *si_cert = NULL;
                OSSL_STORE_INFO *si_ca = NULL;

                if ((ctx = sk_OSSL_STORE_INFO_new_null()) != NULL
                    && (si_pkey = OSSL_STORE_INFO_new_PKEY(pkey)) != NULL
                    && sk_OSSL_STORE_INFO_push(ctx, si_pkey) != 0
                    && (si_cert = OSSL_STORE_INFO_new_CERT(cert)) != NULL
                    && sk_OSSL_STORE_INFO_push(ctx, si_cert) != 0) {
                    ok = 1;
                    si_pkey = NULL;
                    si_cert = NULL;

                    while(sk_X509_num(chain) > 0) {
                        X509 *ca = sk_X509_value(chain, 0);

                        if ((si_ca = OSSL_STORE_INFO_new_CERT(ca)) == NULL
                            || sk_OSSL_STORE_INFO_push(ctx, si_ca) == 0) {
                            ok = 0;
                            break;
                        }
                        si_ca = NULL;
                        (void)sk_X509_shift(chain);
                    }
                }
                if (!ok) {
                    OSSL_STORE_INFO_free(si_ca);
                    OSSL_STORE_INFO_free(si_cert);
                    OSSL_STORE_INFO_free(si_pkey);
                    sk_OSSL_STORE_INFO_pop_free(ctx, OSSL_STORE_INFO_free);
                    EVP_PKEY_free(pkey);
                    X509_free(cert);
                    sk_X509_pop_free(chain, X509_free);
                    ctx = NULL;
                }
                *pctx = ctx;
            }
        }
     p12_end:
        PKCS12_free(p12);
        if (!ok)
            return NULL;
    }

    if (ctx != NULL)
        store_info = sk_OSSL_STORE_INFO_shift(ctx);

    return store_info;
}
static int eof_PKCS12(void *ctx_)
{
    STACK_OF(OSSL_STORE_INFO) *ctx = ctx_;

    return ctx == NULL || sk_OSSL_STORE_INFO_num(ctx) == 0;
}
static void destroy_ctx_PKCS12(void **pctx)
{
    STACK_OF(OSSL_STORE_INFO) *ctx = *pctx;

    sk_OSSL_STORE_INFO_pop_free(ctx, OSSL_STORE_INFO_free);
    *pctx = NULL;
}
static FILE_HANDLER PKCS12_handler = {
    "PKCS12",
    try_decode_PKCS12,
    eof_PKCS12,
    destroy_ctx_PKCS12,
    1                            /* repeatable */
};

int pem_check_suffix(const char *pem_str, const char *suffix);
static OSSL_STORE_INFO *try_decode_PrivateKey(const char *pem_name,
                                              const char *pem_header,
@@ -352,6 +467,7 @@ static FILE_HANDLER X509CRL_handler = {
};

static const FILE_HANDLER *file_handlers[] = {
    &PKCS12_handler,
    &X509Certificate_handler,
    &X509CRL_handler,
    &params_handler,
+6 −0
Original line number Diff line number Diff line
@@ -57,12 +57,16 @@ static const ERR_STRING_DATA OSSL_STORE_str_functs[] = {
     "ossl_store_unregister_loader_int"},
    {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_TRY_DECODE_PARAMS, 0),
     "try_decode_params"},
    {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_TRY_DECODE_PKCS12, 0),
     "try_decode_PKCS12"},
    {0, NULL}
};

static const ERR_STRING_DATA OSSL_STORE_str_reasons[] = {
    {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE),
    "ambiguous content type"},
    {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC),
    "error verifying pkcs12 mac"},
    {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_INVALID_SCHEME),
    "invalid scheme"},
    {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_IS_NOT_A), "is not a"},
@@ -73,6 +77,8 @@ static const ERR_STRING_DATA OSSL_STORE_str_reasons[] = {
    {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_NAME), "not a name"},
    {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_PARAMETERS),
    "not parameters"},
    {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR),
    "passphrase callback error"},
    {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE),
    "path must be absolute"},
    {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED),
+3 −0
Original line number Diff line number Diff line
@@ -45,11 +45,13 @@ int ERR_load_OSSL_STORE_strings(void);
# define OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT      117
# define OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT    116
# define OSSL_STORE_F_TRY_DECODE_PARAMS                   121
# define OSSL_STORE_F_TRY_DECODE_PKCS12                   122

/*
 * OSSL_STORE reason codes.
 */
# define OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE              107
# define OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC          113
# define OSSL_STORE_R_INVALID_SCHEME                      106
# define OSSL_STORE_R_IS_NOT_A                            112
# define OSSL_STORE_R_NOT_A_CERTIFICATE                   100
@@ -57,6 +59,7 @@ int ERR_load_OSSL_STORE_strings(void);
# define OSSL_STORE_R_NOT_A_KEY                           102
# define OSSL_STORE_R_NOT_A_NAME                          103
# define OSSL_STORE_R_NOT_PARAMETERS                      104
# define OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR           114
# define OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE               108
# define OSSL_STORE_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED 109
# define OSSL_STORE_R_UNREGISTERED_SCHEME                 105