Exemple #1
0
/**
 * Adds all subjects in a PKCS12 files and notifies the frontend of them.
 */
static TokenError _backend_addFile(Backend *backend,
                                   const char *data, size_t length,
                                   void *tag) {
    SharedPKCS12 *p12 = pkcs12_parse(data, length);
    if (!p12) return TokenError_BadFile;
    
    STACK_OF(X509) *certList = pkcs12_listCerts(p12->data);
    if (!certList) return TokenError_Unknown;
    
    int certCount = sk_X509_num(certList);
    for (int i = 0; i < certCount; i++) {
        X509 *x = sk_X509_value(certList, i);
        
        if (!certutil_hasKeyUsage(x, backend->notifier->keyUsage)) goto dontAddCert;
        
        X509_NAME *id = X509_get_subject_name(x);
        if (!certutil_matchSubjectFilter(backend->notifier->subjectFilter, id))
            goto dontAddCert;
        
        PKCS12Token *token = createToken(backend, p12, id, tag);
        if (token) {
            backend->notifier->notifyFunction((Token*)token, TokenChange_Added);
            continue;
        }
        
      dontAddCert:
        X509_free(x);
    }
    
    pkcs12_release(p12);
    return TokenError_Success;
}
Exemple #2
0
/**
 * Returns a list of DER-BASE64 encoded certificates, from the subject
 * to the root CA.
 */
static TokenError _backend_getBase64Chain(const PKCS12Token *token,
                                          char ***certs, size_t *count) {
    
    STACK_OF(X509) *certList = pkcs12_listCerts(token->sharedP12->data);
    if (!certList) return TokenError_Unknown;
    
    X509 *cert = certutil_findCert(certList, token->subjectName,
                                   token->base.backend->notifier->keyUsage,
                                   false);
    if (!cert) {
        sk_X509_pop_free(certList, X509_free);
        return TokenError_Unknown;
    }
    
    *count = 0;
    *certs = NULL;
    if (!certutil_addToList(certs, count, cert)) goto error;
    
    X509_NAME *issuer = X509_get_issuer_name(cert);
    while (issuer != NULL) {
        cert = certutil_findCert(certList, issuer, KeyUsage_Issuing, false);
        if (!cert) break;
        
        issuer = X509_get_issuer_name(cert);
        
        if (!certutil_addToList(certs, count, cert)) goto error;
    }
    
    sk_X509_pop_free(certList, X509_free);
    return TokenError_Success;
    
  error:
    certutil_freeList(certs, count);
    return TokenError_Unknown;
}
Exemple #3
0
static TokenError _backend_sign(PKCS12Token *token,
                                const char *message, size_t messagelen,
                                char **signature, size_t *siglen) {
    
    if (!message || !signature || !siglen) {
        assert(false);
        return TokenError_Unknown;
    }
    
    if (messagelen >= UINT_MAX) return TokenError_MessageTooLong;
    
    // Find the certificate for the token
    STACK_OF(X509) *certList = pkcs12_listCerts(token->sharedP12->data);
    if (!certList) return TokenError_Unknown;
    
    X509 *cert = certutil_findCert(certList, token->subjectName,
                                   token->base.backend->notifier->keyUsage,
                                   false);
    if (!cert) {
        sk_X509_pop_free(certList, X509_free);
        return TokenError_Unknown;
    }
    
    // Get the corresponding private key
    EVP_PKEY *key = getPrivateKey(token->sharedP12->data, cert,
                                  token->base.password);
    sk_X509_pop_free(certList, X509_free);
    
    if (!key) return TokenError_BadPassword;
    
    // Sign with the default crypto with SHA1
    unsigned int sig_len = EVP_PKEY_size(key);
    *siglen = sig_len;
    *signature = malloc(sig_len);
    
    EVP_MD_CTX sig_ctx;
    EVP_MD_CTX_init(&sig_ctx);
    bool success = (EVP_SignInit(&sig_ctx, EVP_sha1()) &&
                    EVP_SignUpdate(&sig_ctx, message, messagelen) &&
                    EVP_SignFinal(&sig_ctx, (unsigned char*)*signature,
                                  &sig_len, key));
    EVP_MD_CTX_cleanup(&sig_ctx);
    EVP_PKEY_free(key);
    *siglen = sig_len;
    
    if (success) {
        return TokenError_Success;
    } else {
        certutil_updateErrorString();
        free(*signature);
        return TokenError_SignatureFailure;
    }
}