NOEXPORT int load_pkcs12_file(SERVICE_OPTIONS *section) {
    size_t len;
    int i, success;
    BIO *bio=NULL;
    PKCS12 *p12=NULL;
    X509 *cert=NULL;
    STACK_OF(X509) *ca=NULL;
    EVP_PKEY *pkey=NULL;
    char pass[PEM_BUFSIZE];

    s_log(LOG_INFO, "Loading certificate and private key from file: %s",
        section->cert);
    if(file_permissions(section->cert))
        return 1; /* FAILED */

    bio=BIO_new_file(section->cert, "rb");
    if(!bio) {
        sslerror("BIO_new_file");
        return 1; /* FAILED */
    }
    p12=d2i_PKCS12_bio(bio, NULL);
    if(!p12) {
        sslerror("d2i_PKCS12_bio");
        BIO_free(bio);
        return 1; /* FAILED */
    }
    BIO_free(bio);

    /* try the cached value first */
    set_prompt(section->cert);
    len=(size_t)cache_passwd_get_cb(pass, sizeof pass, 0, NULL);
    if(len>=sizeof pass)
        len=sizeof pass-1;
    pass[len]='\0'; /* null-terminate */
    success=PKCS12_parse(p12, pass, &pkey, &cert, &ca);

    /* invoke the UI */
    for(i=0; !success && i<3; i++) {
        if(!ui_retry())
            break;
        if(i==0) { /* silence the cached attempt */
            ERR_clear_error();
        } else {
            sslerror_queue(); /* dump the error queue */
            s_log(LOG_ERR, "Wrong passphrase: retrying");
        }
        /* invoke the UI on subsequent calls */
        len=(size_t)cache_passwd_set_cb(pass, sizeof pass, 0, NULL);
        if(len>=sizeof pass)
            len=sizeof pass-1;
        pass[len]='\0'; /* null-terminate */
        success=PKCS12_parse(p12, pass, &pkey, &cert, &ca);
    }
    if(!success) {
        sslerror("PKCS12_parse");
        PKCS12_free(p12);
        return 1; /* FAILED */
    }

    PKCS12_free(p12);

    if(!SSL_CTX_use_certificate(section->ctx, cert)) {
        sslerror("SSL_CTX_use_certificate");
        return 1; /* FAILED */
    }
    if(!SSL_CTX_use_PrivateKey(section->ctx, pkey)) {
        sslerror("SSL_CTX_use_PrivateKey");
        return 1; /* FAILED */
    }
    s_log(LOG_INFO, "Certificate and private key loaded from file: %s",
        section->cert);
    return 0; /* OK */
}
NOEXPORT int load_pkcs12_file(SERVICE_OPTIONS *section) {
    size_t len;
    int i, success;
    BIO *bio=NULL;
    PKCS12 *p12=NULL;
    X509 *cert=NULL;
    STACK_OF(X509) *ca=NULL;
    EVP_PKEY *pkey=NULL;
    char pass[PEM_BUFSIZE];

    s_log(LOG_INFO, "Loading certificate and private key from file: %s",
        section->cert);
    if(file_permissions(section->cert))
        return 1;  

    bio=BIO_new_file(section->cert, "rb");
    if(!bio) {
        sslerror("BIO_new_file");
        return 1;  
    }
    p12=d2i_PKCS12_bio(bio, NULL);
    if(!p12) {
        sslerror("d2i_PKCS12_bio");
        BIO_free(bio);
        return 1;  
    }
    BIO_free(bio);

     
    set_prompt(section->cert);
    len=(size_t)cache_passwd_get_cb(pass, sizeof pass, 0, NULL);
    if(len>=sizeof pass)
        len=sizeof pass-1;
    pass[len]='\0';  
    success=PKCS12_parse(p12, pass, &pkey, &cert, &ca);

     
    for(i=0; !success && i<3; i++) {
        if(!ui_retry())
            break;
        if(i==0) {  
            ERR_clear_error();
        } else {
            sslerror_queue();  
            s_log(LOG_ERR, "Wrong passphrase: retrying");
        }
         
        len=(size_t)cache_passwd_set_cb(pass, sizeof pass, 0, NULL);
        if(len>=sizeof pass)
            len=sizeof pass-1;
        pass[len]='\0';  
        success=PKCS12_parse(p12, pass, &pkey, &cert, &ca);
    }
    if(!success) {
        sslerror("PKCS12_parse");
        PKCS12_free(p12);
        return 1;  
    }

    PKCS12_free(p12);

    if(!SSL_CTX_use_certificate(section->ctx, cert)) {
        sslerror("SSL_CTX_use_certificate");
        return 1;  
    }
    if(!SSL_CTX_use_PrivateKey(section->ctx, pkey)) {
        sslerror("SSL_CTX_use_PrivateKey");
        return 1;  
    }
    s_log(LOG_INFO, "Certificate and private key loaded from file: %s",
        section->cert);
    return 0;  
}