Ejemplo n.º 1
0
Archivo: cms.c Proyecto: InvLim/heimdal
static int
sig_process(hx509_context context, void *ctx, hx509_cert cert)
{
    struct sigctx *sigctx = ctx;
    heim_octet_string buf, sigdata = { 0, NULL };
    SignerInfo *signer_info = NULL;
    AlgorithmIdentifier digest;
    size_t size;
    void *ptr;
    int ret;
    SignedData *sd = &sigctx->sd;
    hx509_path path;

    memset(&digest, 0, sizeof(digest));
    memset(&path, 0, sizeof(path));

    if (_hx509_cert_private_key(cert) == NULL) {
	hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
			       "Private key missing for signing");
	return HX509_PRIVATE_KEY_MISSING;
    }

    if (sigctx->digest_alg) {
	ret = copy_AlgorithmIdentifier(sigctx->digest_alg, &digest);
	if (ret)
	    hx509_clear_error_string(context);
    } else {
	ret = hx509_crypto_select(context, HX509_SELECT_DIGEST,
				  _hx509_cert_private_key(cert),
				  sigctx->peer, &digest);
    }
    if (ret)
	goto out;

    /*
     * Allocate on more signerInfo and do the signature processing
     */

    ptr = realloc(sd->signerInfos.val,
		  (sd->signerInfos.len + 1) * sizeof(sd->signerInfos.val[0]));
    if (ptr == NULL) {
	ret = ENOMEM;
	goto out;
    }
    sd->signerInfos.val = ptr;

    signer_info = &sd->signerInfos.val[sd->signerInfos.len];

    memset(signer_info, 0, sizeof(*signer_info));

    signer_info->version = 1;

    ret = fill_CMSIdentifier(cert, sigctx->cmsidflag, &signer_info->sid);
    if (ret) {
	hx509_clear_error_string(context);
	goto out;
    }

    signer_info->signedAttrs = NULL;
    signer_info->unsignedAttrs = NULL;

    ret = copy_AlgorithmIdentifier(&digest, &signer_info->digestAlgorithm);
    if (ret) {
	hx509_clear_error_string(context);
	goto out;
    }

    /*
     * If it isn't pkcs7-data send signedAttributes
     */

    if (der_heim_oid_cmp(sigctx->eContentType, &asn1_oid_id_pkcs7_data) != 0) {
	CMSAttributes sa;
	heim_octet_string sig;

	ALLOC(signer_info->signedAttrs, 1);
	if (signer_info->signedAttrs == NULL) {
	    ret = ENOMEM;
	    goto out;
	}

	ret = _hx509_create_signature(context,
				      NULL,
				      &digest,
				      &sigctx->content,
				      NULL,
				      &sig);
	if (ret)
	    goto out;

	ASN1_MALLOC_ENCODE(MessageDigest,
			   buf.data,
			   buf.length,
			   &sig,
			   &size,
			   ret);
	der_free_octet_string(&sig);
	if (ret) {
	    hx509_clear_error_string(context);
	    goto out;
	}
	if (size != buf.length)
	    _hx509_abort("internal ASN.1 encoder error");

	ret = add_one_attribute(&signer_info->signedAttrs->val,
				&signer_info->signedAttrs->len,
				&asn1_oid_id_pkcs9_messageDigest,
				&buf);
	if (ret) {
	    free(buf.data);
	    hx509_clear_error_string(context);
	    goto out;
	}


	ASN1_MALLOC_ENCODE(ContentType,
			   buf.data,
			   buf.length,
			   sigctx->eContentType,
			   &size,
			   ret);
	if (ret)
	    goto out;
	if (size != buf.length)
	    _hx509_abort("internal ASN.1 encoder error");

	ret = add_one_attribute(&signer_info->signedAttrs->val,
				&signer_info->signedAttrs->len,
				&asn1_oid_id_pkcs9_contentType,
				&buf);
	if (ret) {
	    free(buf.data);
	    hx509_clear_error_string(context);
	    goto out;
	}

	sa.val = signer_info->signedAttrs->val;
	sa.len = signer_info->signedAttrs->len;

	ASN1_MALLOC_ENCODE(CMSAttributes,
			   sigdata.data,
			   sigdata.length,
			   &sa,
			   &size,
			   ret);
	if (ret) {
	    hx509_clear_error_string(context);
	    goto out;
	}
	if (size != sigdata.length)
	    _hx509_abort("internal ASN.1 encoder error");
    } else {
	sigdata.data = sigctx->content.data;
	sigdata.length = sigctx->content.length;
    }

    {
	AlgorithmIdentifier sigalg;

	ret = hx509_crypto_select(context, HX509_SELECT_PUBLIC_SIG,
				  _hx509_cert_private_key(cert), sigctx->peer,
				  &sigalg);
	if (ret)
	    goto out;

	ret = _hx509_create_signature(context,
				      _hx509_cert_private_key(cert),
				      &sigalg,
				      &sigdata,
				      &signer_info->signatureAlgorithm,
				      &signer_info->signature);
	free_AlgorithmIdentifier(&sigalg);
	if (ret)
	    goto out;
    }

    sigctx->sd.signerInfos.len++;
    signer_info = NULL;

    /*
     * Provide best effort path
     */
    if (sigctx->certs) {
	unsigned int i;

	if (sigctx->pool && sigctx->leafonly == 0) {
	    _hx509_calculate_path(context,
				  HX509_CALCULATE_PATH_NO_ANCHOR,
				  time(NULL),
				  sigctx->anchors,
				  0,
				  cert,
				  sigctx->pool,
				  &path);
	} else
	    _hx509_path_append(context, &path, cert);

	for (i = 0; i < path.len; i++) {
	    /* XXX remove dups */
	    ret = hx509_certs_add(context, sigctx->certs, path.val[i]);
	    if (ret) {
		hx509_clear_error_string(context);
		goto out;
	    }
	}
    }

 out:
    if (signer_info)
	free_SignerInfo(signer_info);
    if (sigdata.data != sigctx->content.data)
	der_free_octet_string(&sigdata);
    _hx509_path_free(&path);
    free_AlgorithmIdentifier(&digest);

    return ret;
}
Ejemplo n.º 2
0
CK_RV
C_Sign(CK_SESSION_HANDLE hSession,
       CK_BYTE_PTR pData,
       CK_ULONG ulDataLen,
       CK_BYTE_PTR pSignature,
       CK_ULONG_PTR pulSignatureLen)
{
    struct session_state *state;
    struct st_object *o;
    CK_RV ret;
    int hret;
    const AlgorithmIdentifier *alg;
    heim_octet_string sig, data;

    INIT_CONTEXT();
    st_logf("Sign\n");
    VERIFY_SESSION_HANDLE(hSession, &state);

    sig.data = NULL;
    sig.length = 0;

    if (state->sign_object == -1)
	return CKR_ARGUMENTS_BAD;

    if (pulSignatureLen == NULL) {
	st_logf("signature len NULL\n");
	ret = CKR_ARGUMENTS_BAD;
	goto out;
    }

    if (pData == NULL_PTR) {
	st_logf("data NULL\n");
	ret = CKR_ARGUMENTS_BAD;
	goto out;
    }

    o = soft_token.object.objs[state->sign_object];

    if (hx509_cert_have_private_key(o->cert) == 0) {
	st_logf("private key NULL\n");
	return CKR_ARGUMENTS_BAD;
    }

    switch(state->sign_mechanism->mechanism) {
    case CKM_RSA_PKCS:
	alg = hx509_signature_rsa_pkcs1_x509();
	break;
    default:
	ret = CKR_FUNCTION_NOT_SUPPORTED;
	goto out;
    }

    data.data = pData;
    data.length = ulDataLen;

    hret = _hx509_create_signature(context,
				   _hx509_cert_private_key(o->cert),
				   alg,
				   &data,
				   NULL,
				   &sig);
    if (hret) {
	ret = CKR_DEVICE_ERROR;
	goto out;
    }
    *pulSignatureLen = sig.length;

    if (pSignature != NULL_PTR)
	memcpy(pSignature, sig.data, sig.length);

    ret = CKR_OK;
 out:
    if (sig.data) {
	memset(sig.data, 0, sig.length);
	der_free_octet_string(&sig);
    }
    return ret;
}
Ejemplo n.º 3
0
Archivo: req.c Proyecto: gojdic/samba
int
_hx509_request_to_pkcs10(hx509_context context,
			 const hx509_request req,
			 const hx509_private_key signer,
			 heim_octet_string *request)
{
    CertificationRequest r;
    heim_octet_string data, os;
    int ret;
    size_t size;

    if (req->name == NULL) {
	hx509_set_error_string(context, 0, EINVAL,
			       "PKCS10 needs to have a subject");
	return EINVAL;
    }

    memset(&r, 0, sizeof(r));
    memset(request, 0, sizeof(*request));

    r.certificationRequestInfo.version = pkcs10_v1;

    ret = copy_Name(&req->name->der_name,
		    &r.certificationRequestInfo.subject);
    if (ret)
	goto out;
    ret = copy_SubjectPublicKeyInfo(&req->key,
				    &r.certificationRequestInfo.subjectPKInfo);
    if (ret)
	goto out;
    r.certificationRequestInfo.attributes =
	calloc(1, sizeof(*r.certificationRequestInfo.attributes));
    if (r.certificationRequestInfo.attributes == NULL) {
	ret = ENOMEM;
	goto out;
    }

    ASN1_MALLOC_ENCODE(CertificationRequestInfo, data.data, data.length,
		       &r.certificationRequestInfo, &size, ret);
    if (ret)
	goto out;
    if (data.length != size)
	abort();

    ret = _hx509_create_signature(context,
				  signer,
				  _hx509_crypto_default_sig_alg,
				  &data,
				  &r.signatureAlgorithm,
				  &os);
    free(data.data);
    if (ret)
	goto out;
    r.signature.data = os.data;
    r.signature.length = os.length * 8;

    ASN1_MALLOC_ENCODE(CertificationRequest, data.data, data.length,
		       &r, &size, ret);
    if (ret)
	goto out;
    if (data.length != size)
	abort();

    *request = data;

out:
    free_CertificationRequest(&r);

    return ret;
}
Ejemplo n.º 4
0
static int
add_to_req(hx509_context context, void *ptr, hx509_cert cert)
{
    struct ocsp_add_ctx *ctx = ptr;
    OCSPInnerRequest *one;
    hx509_cert parent = NULL;
    Certificate *p, *c = _hx509_get_cert(cert);
    heim_octet_string os;
    int ret;
    hx509_query q;
    void *d;

    d = realloc(ctx->req->requestList.val,
		sizeof(ctx->req->requestList.val[0]) *
		(ctx->req->requestList.len + 1));
    if (d == NULL)
	return ENOMEM;
    ctx->req->requestList.val = d;

    one = &ctx->req->requestList.val[ctx->req->requestList.len];
    memset(one, 0, sizeof(*one));

    _hx509_query_clear(&q);

    q.match |= HX509_QUERY_FIND_ISSUER_CERT;
    q.subject = c;

    ret = hx509_certs_find(context, ctx->certs, &q, &parent);
    if (ret)
	goto out;

    if (ctx->parent) {
	if (hx509_cert_cmp(ctx->parent, parent) != 0) {
	    ret = HX509_REVOKE_NOT_SAME_PARENT;
	    hx509_set_error_string(context, 0, ret,
				   "Not same parent certifate as "
				   "last certificate in request");
	    goto out;
	}
    } else
	ctx->parent = hx509_cert_ref(parent);

    p = _hx509_get_cert(parent);

    ret = copy_AlgorithmIdentifier(ctx->digest, &one->reqCert.hashAlgorithm);
    if (ret)
	goto out;

    ret = _hx509_create_signature(context,
				  NULL,
				  &one->reqCert.hashAlgorithm,
				  &c->tbsCertificate.issuer._save,
				  NULL,
				  &one->reqCert.issuerNameHash);
    if (ret)
	goto out;

    os.data = p->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
    os.length =
	p->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;

    ret = _hx509_create_signature(context,
				  NULL,
				  &one->reqCert.hashAlgorithm,
				  &os,
				  NULL,
				  &one->reqCert.issuerKeyHash);
    if (ret)
	goto out;

    ret = copy_CertificateSerialNumber(&c->tbsCertificate.serialNumber,
				       &one->reqCert.serialNumber);
    if (ret)
	goto out;

    ctx->req->requestList.len++;
out:
    hx509_cert_free(parent);
    if (ret) {
	free_OCSPInnerRequest(one);
	memset(one, 0, sizeof(*one));
    }

    return ret;
}
Ejemplo n.º 5
0
static int
ecdsa_create_signature(hx509_context context,
                       const struct signature_alg *sig_alg,
                       const hx509_private_key signer,
                       const AlgorithmIdentifier *alg,
                       const heim_octet_string *data,
                       AlgorithmIdentifier *signatureAlgorithm,
                       heim_octet_string *sig)
{
    const AlgorithmIdentifier *digest_alg;
    heim_octet_string indata;
    const heim_oid *sig_oid;
    unsigned int siglen;
    int ret;

    if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) != 0)
        _hx509_abort("internal error passing private key to wrong ops");

    sig_oid = sig_alg->sig_oid;
    digest_alg = sig_alg->digest_alg;

    if (signatureAlgorithm) {
        ret = _hx509_set_digest_alg(signatureAlgorithm, sig_oid,
                                    "\x05\x00", 2);
        if (ret) {
            hx509_clear_error_string(context);
            return ret;
        }
    }

    ret = _hx509_create_signature(context,
                                  NULL,
                                  digest_alg,
                                  data,
                                  NULL,
                                  &indata);
    if (ret)
        goto error;

    sig->length = ECDSA_size(signer->private_key.ecdsa);
    sig->data = malloc(sig->length);
    if (sig->data == NULL) {
        der_free_octet_string(&indata);
        ret = ENOMEM;
        hx509_set_error_string(context, 0, ret, "out of memory");
        goto error;
    }

    siglen = sig->length;

    ret = ECDSA_sign(-1, indata.data, indata.length,
                     sig->data, &siglen, signer->private_key.ecdsa);
    der_free_octet_string(&indata);
    if (ret != 1) {
        ret = HX509_CMS_FAILED_CREATE_SIGATURE;
        hx509_set_error_string(context, 0, ret,
                               "ECDSA sign failed: %d", ret);
        goto error;
    }
    if (siglen > sig->length)
        _hx509_abort("ECDSA signature prelen longer the output len");

    sig->length = siglen;

    return 0;
error:
    if (signatureAlgorithm)
        free_AlgorithmIdentifier(signatureAlgorithm);
    return ret;
}
Ejemplo n.º 6
0
static int
ecdsa_verify_signature(hx509_context context,
                       const struct signature_alg *sig_alg,
                       const Certificate *signer,
                       const AlgorithmIdentifier *alg,
                       const heim_octet_string *data,
                       const heim_octet_string *sig)
{
    const AlgorithmIdentifier *digest_alg;
    const SubjectPublicKeyInfo *spi;
    heim_octet_string digest;
    int ret;
    EC_KEY *key = NULL;
    int groupnid;
    EC_GROUP *group;
    const unsigned char *p;
    long len;

    digest_alg = sig_alg->digest_alg;

    ret = _hx509_create_signature(context,
                                  NULL,
                                  digest_alg,
                                  data,
                                  NULL,
                                  &digest);
    if (ret)
        return ret;

    /* set up EC KEY */
    spi = &signer->tbsCertificate.subjectPublicKeyInfo;

    if (der_heim_oid_cmp(&spi->algorithm.algorithm, ASN1_OID_ID_ECPUBLICKEY) != 0)
        return HX509_CRYPTO_SIG_INVALID_FORMAT;

    /*
     * Find the group id
     */

    ret = parse_ECParameters(context, spi->algorithm.parameters, &groupnid);
    if (ret) {
        der_free_octet_string(&digest);
        return ret;
    }

    /*
     * Create group, key, parse key
     */

    key = EC_KEY_new();
    group = EC_GROUP_new_by_curve_name(groupnid);
    EC_KEY_set_group(key, group);
    EC_GROUP_free(group);

    p = spi->subjectPublicKey.data;
    len = spi->subjectPublicKey.length / 8;

    if (o2i_ECPublicKey(&key, &p, len) == NULL) {
        EC_KEY_free(key);
        return HX509_CRYPTO_SIG_INVALID_FORMAT;
    }

    ret = ECDSA_verify(-1, digest.data, digest.length,
                       sig->data, sig->length, key);
    der_free_octet_string(&digest);
    EC_KEY_free(key);
    if (ret != 1) {
        ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
        return ret;
    }

    return 0;
}