Exemplo n.º 1
0
int
hx509_peer_info_set_cms_algs(hx509_context context,
			     hx509_peer_info peer,
			     const AlgorithmIdentifier *val,
			     size_t len)
{
    size_t i;

    free_cms_alg(peer);

    peer->val = calloc(len, sizeof(*peer->val));
    if (peer->val == NULL) {
	peer->len = 0;
	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
	return ENOMEM;
    }
    peer->len = len;
    for (i = 0; i < len; i++) {
	int ret;
	ret = copy_AlgorithmIdentifier(&val[i], &peer->val[i]);
	if (ret) {
	    hx509_clear_error_string(context);
	    free_cms_alg(peer);
	    return ret;
	}
    }
    return 0;
}
Exemplo n.º 2
0
int
_hx509_collector_private_key_add(hx509_context context,
				 struct hx509_collector *c,
				 const AlgorithmIdentifier *alg,
				 hx509_private_key private_key,
				 const heim_octet_string *key_data,
				 const heim_octet_string *localKeyId)
{
    struct private_key *key;
    void *d;
    int ret;

    key = calloc(1, sizeof(*key));
    if (key == NULL)
	return ENOMEM;

    d = realloc(c->val.data, (c->val.len + 1) * sizeof(c->val.data[0]));
    if (d == NULL) {
	free(key);
	hx509_set_error_string(context, 0, ENOMEM, "Out of memory");
	return ENOMEM;
    }
    c->val.data = d;
	
    ret = copy_AlgorithmIdentifier(alg, &key->alg);
    if (ret) {
	hx509_set_error_string(context, 0, ret, "Failed to copy "
			       "AlgorithmIdentifier");
	goto out;
    }
    if (private_key) {
	key->private_key = private_key;
    } else {
	ret = hx509_parse_private_key(context, alg,
				       key_data->data, key_data->length,
				       HX509_KEY_FORMAT_DER,
				       &key->private_key);
	if (ret)
	    goto out;
    }
    if (localKeyId) {
	ret = der_copy_octet_string(localKeyId, &key->localKeyId);
	if (ret) {
	    hx509_set_error_string(context, 0, ret,
				   "Failed to copy localKeyId");
	    goto out;
	}
    } else
	memset(&key->localKeyId, 0, sizeof(key->localKeyId));

    c->val.data[c->val.len] = key;
    c->val.len++;

out:
    if (ret)
	free_private_key(key);

    return ret;
}
Exemplo n.º 3
0
Arquivo: ca.c Projeto: cg2v/heimdal
int
hx509_ca_tbs_set_signature_algorithm(hx509_context context,
				     hx509_ca_tbs tbs,
				     const AlgorithmIdentifier *sigalg)
{
    int ret;

    tbs->sigalg = calloc(1, sizeof(*tbs->sigalg));
    if (tbs->sigalg == NULL) {
	hx509_set_error_string(context, 0, ENOMEM, "Out of memory");
	return ENOMEM;
    }
    ret = copy_AlgorithmIdentifier(sigalg, tbs->sigalg);
    if (ret) {
	free(tbs->sigalg);
	tbs->sigalg = NULL;
	return ret;
    }
    return 0;
}
Exemplo n.º 4
0
int
hx509_peer_info_add_cms_alg(hx509_context context,
			    hx509_peer_info peer,
			    const AlgorithmIdentifier *val)
{
    void *ptr;
    int ret;

    ptr = realloc(peer->val, sizeof(peer->val[0]) * (peer->len + 1));
    if (ptr == NULL) {
	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
	return ENOMEM;
    }
    ret = copy_AlgorithmIdentifier(val, &peer->val[peer->len]);
    if (ret == 0)
	peer->len += 1;
    else
	hx509_set_error_string(context, 0, ret, "out of memory");
    return ret;
}
Exemplo n.º 5
0
static int
ca_sign(hx509_context context,
	hx509_ca_tbs tbs,
	hx509_private_key signer,
	const AuthorityKeyIdentifier *ai,
	const Name *issuername,
	hx509_cert *certificate)
{
    heim_octet_string data;
    Certificate c;
    TBSCertificate *tbsc;
    size_t size;
    int ret;
    const AlgorithmIdentifier *sigalg;
    time_t notBefore;
    time_t notAfter;
    unsigned key_usage;

    sigalg = _hx509_crypto_default_sig_alg;

    memset(&c, 0, sizeof(c));

    /*
     * Default values are: Valid since 24h ago, valid one year into
     * the future, KeyUsage digitalSignature and keyEncipherment set,
     * and keyCertSign for CA certificates.
     */
    notBefore = tbs->notBefore;
    if (notBefore == 0)
	notBefore = time(NULL) - 3600 * 24;
    notAfter = tbs->notAfter;
    if (notAfter == 0)
	notAfter = time(NULL) + 3600 * 24 * 365;

    key_usage = tbs->key_usage;
    if (key_usage == 0) {
	KeyUsage ku;
	memset(&ku, 0, sizeof(ku));
	ku.digitalSignature = 1;
	ku.keyEncipherment = 1;
	key_usage = KeyUsage2int(ku);
    }

    if (tbs->flags.ca) {
	KeyUsage ku;
	memset(&ku, 0, sizeof(ku));
	ku.keyCertSign = 1;
	ku.cRLSign = 1;
	key_usage |= KeyUsage2int(ku);
    }

    /*
     *
     */

    tbsc = &c.tbsCertificate;

    if (tbs->flags.key == 0) {
	ret = EINVAL;
	hx509_set_error_string(context, 0, ret, "No public key set");
	return ret;
    }
    /*
     * Don't put restrictions on proxy certificate's subject name, it
     * will be generated below.
     */
    if (!tbs->flags.proxy) {
	if (tbs->subject == NULL) {
	    hx509_set_error_string(context, 0, EINVAL, "No subject name set");
	    return EINVAL;
	}
	if (hx509_name_is_null_p(tbs->subject) && tbs->san.len == 0) {
	    hx509_set_error_string(context, 0, EINVAL,
				   "NULL subject and no SubjectAltNames");
	    return EINVAL;
	}
    }
    if (tbs->flags.ca && tbs->flags.proxy) {
	hx509_set_error_string(context, 0, EINVAL, "Can't be proxy and CA "
			       "at the same time");
	return EINVAL;
    }
    if (tbs->flags.proxy) {
	if (tbs->san.len > 0) {
	    hx509_set_error_string(context, 0, EINVAL,
				   "Proxy certificate is not allowed "
				   "to have SubjectAltNames");
	    return EINVAL;
	}
    }

    /* version         [0]  Version OPTIONAL, -- EXPLICIT nnn DEFAULT 1, */
    tbsc->version = calloc(1, sizeof(*tbsc->version));
    if (tbsc->version == NULL) {
	ret = ENOMEM;
	hx509_set_error_string(context, 0, ret, "Out of memory");
	goto out;
    }
    *tbsc->version = rfc3280_version_3;
    /* serialNumber         CertificateSerialNumber, */
    if (tbs->flags.serial) {
	ret = der_copy_heim_integer(&tbs->serial, &tbsc->serialNumber);
	if (ret) {
	    hx509_set_error_string(context, 0, ret, "Out of memory");
	    goto out;
	}
    } else {
	tbsc->serialNumber.length = 20;
	tbsc->serialNumber.data = malloc(tbsc->serialNumber.length);
	if (tbsc->serialNumber.data == NULL){
	    ret = ENOMEM;
	    hx509_set_error_string(context, 0, ret, "Out of memory");
	    goto out;
	}
	/* XXX diffrent */
	RAND_bytes(tbsc->serialNumber.data, tbsc->serialNumber.length);
	((unsigned char *)tbsc->serialNumber.data)[0] &= 0x7f;
    }
    /* signature            AlgorithmIdentifier, */
    ret = copy_AlgorithmIdentifier(sigalg, &tbsc->signature);
    if (ret) {
	hx509_set_error_string(context, 0, ret, "Failed to copy sigature alg");
	goto out;
    }
    /* issuer               Name, */
    if (issuername)
	ret = copy_Name(issuername, &tbsc->issuer);
    else
	ret = hx509_name_to_Name(tbs->subject, &tbsc->issuer);
    if (ret) {
	hx509_set_error_string(context, 0, ret, "Failed to copy issuer name");
	goto out;
    }
    /* validity             Validity, */
    tbsc->validity.notBefore.element = choice_Time_generalTime;
    tbsc->validity.notBefore.u.generalTime = notBefore;
    tbsc->validity.notAfter.element = choice_Time_generalTime;
    tbsc->validity.notAfter.u.generalTime = notAfter;
    /* subject              Name, */
    if (tbs->flags.proxy) {
	ret = build_proxy_prefix(context, &tbsc->issuer, &tbsc->subject);
	if (ret)
	    goto out;
    } else {
	ret = hx509_name_to_Name(tbs->subject, &tbsc->subject);
	if (ret) {
	    hx509_set_error_string(context, 0, ret,
				   "Failed to copy subject name");
	    goto out;
	}
    }
    /* subjectPublicKeyInfo SubjectPublicKeyInfo, */
    ret = copy_SubjectPublicKeyInfo(&tbs->spki, &tbsc->subjectPublicKeyInfo);
    if (ret) {
	hx509_set_error_string(context, 0, ret, "Failed to copy spki");
	goto out;
    }
    /* issuerUniqueID  [1]  IMPLICIT BIT STRING OPTIONAL */
    if (tbs->issuerUniqueID.length) {
	tbsc->issuerUniqueID = calloc(1, sizeof(*tbsc->issuerUniqueID));
	if (tbsc->issuerUniqueID == NULL) {
	    ret = ENOMEM;
	    hx509_set_error_string(context, 0, ret, "Out of memory");
	    goto out;
	}
	ret = der_copy_bit_string(&tbs->issuerUniqueID, tbsc->issuerUniqueID);
	if (ret) {
	    hx509_set_error_string(context, 0, ret, "Out of memory");
	    goto out;
	}
    }
    /* subjectUniqueID [2]  IMPLICIT BIT STRING OPTIONAL */
    if (tbs->subjectUniqueID.length) {
	tbsc->subjectUniqueID = calloc(1, sizeof(*tbsc->subjectUniqueID));
	if (tbsc->subjectUniqueID == NULL) {
	    ret = ENOMEM;
	    hx509_set_error_string(context, 0, ret, "Out of memory");
	    goto out;
	}

	ret = der_copy_bit_string(&tbs->subjectUniqueID, tbsc->subjectUniqueID);
	if (ret) {
	    hx509_set_error_string(context, 0, ret, "Out of memory");
	    goto out;
	}
    }

    /* extensions      [3]  EXPLICIT Extensions OPTIONAL */
    tbsc->extensions = calloc(1, sizeof(*tbsc->extensions));
    if (tbsc->extensions == NULL) {
	ret = ENOMEM;
	hx509_set_error_string(context, 0, ret, "Out of memory");
	goto out;
    }

    /* Add the text BMP string Domaincontroller to the cert */
    if (tbs->flags.domaincontroller) {
	data.data = rk_UNCONST("\x1e\x20\x00\x44\x00\x6f\x00\x6d"
			       "\x00\x61\x00\x69\x00\x6e\x00\x43"
			       "\x00\x6f\x00\x6e\x00\x74\x00\x72"
			       "\x00\x6f\x00\x6c\x00\x6c\x00\x65"
			       "\x00\x72");
	data.length = 34;

	ret = add_extension(context, tbsc, 0,
			    &asn1_oid_id_ms_cert_enroll_domaincontroller,
			    &data);
	if (ret)
	    goto out;
    }

    /* add KeyUsage */
    {
	KeyUsage ku;

	ku = int2KeyUsage(key_usage);
	ASN1_MALLOC_ENCODE(KeyUsage, data.data, data.length, &ku, &size, ret);
	if (ret) {
	    hx509_set_error_string(context, 0, ret, "Out of memory");
	    goto out;
	}
	if (size != data.length)
	    _hx509_abort("internal ASN.1 encoder error");
	ret = add_extension(context, tbsc, 1,
			    &asn1_oid_id_x509_ce_keyUsage, &data);
	free(data.data);
	if (ret)
	    goto out;
    }

    /* add ExtendedKeyUsage */
    if (tbs->eku.len > 0) {
	ASN1_MALLOC_ENCODE(ExtKeyUsage, data.data, data.length,
			   &tbs->eku, &size, ret);
	if (ret) {
	    hx509_set_error_string(context, 0, ret, "Out of memory");
	    goto out;
	}
	if (size != data.length)
	    _hx509_abort("internal ASN.1 encoder error");
	ret = add_extension(context, tbsc, 0,
			    &asn1_oid_id_x509_ce_extKeyUsage, &data);
	free(data.data);
	if (ret)
	    goto out;
    }

    /* add Subject Alternative Name */
    if (tbs->san.len > 0) {
	ASN1_MALLOC_ENCODE(GeneralNames, data.data, data.length,
			   &tbs->san, &size, ret);
	if (ret) {
	    hx509_set_error_string(context, 0, ret, "Out of memory");
	    goto out;
	}
	if (size != data.length)
	    _hx509_abort("internal ASN.1 encoder error");
	ret = add_extension(context, tbsc, 0,
			    &asn1_oid_id_x509_ce_subjectAltName,
			    &data);
	free(data.data);
	if (ret)
	    goto out;
    }

    /* Add Authority Key Identifier */
    if (ai) {
	ASN1_MALLOC_ENCODE(AuthorityKeyIdentifier, data.data, data.length,
			   ai, &size, ret);
	if (ret) {
	    hx509_set_error_string(context, 0, ret, "Out of memory");
	    goto out;
	}
	if (size != data.length)
	    _hx509_abort("internal ASN.1 encoder error");
	ret = add_extension(context, tbsc, 0,
			    &asn1_oid_id_x509_ce_authorityKeyIdentifier,
			    &data);
	free(data.data);
	if (ret)
	    goto out;
    }

    /* Add Subject Key Identifier */
    {
	SubjectKeyIdentifier si;
	unsigned char hash[SHA_DIGEST_LENGTH];

	{
	    EVP_MD_CTX *ctx;

	    ctx = EVP_MD_CTX_create();
	    EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
	    EVP_DigestUpdate(ctx, tbs->spki.subjectPublicKey.data,
			     tbs->spki.subjectPublicKey.length / 8);
	    EVP_DigestFinal_ex(ctx, hash, NULL);
	    EVP_MD_CTX_destroy(ctx);
	}

	si.data = hash;
	si.length = sizeof(hash);

	ASN1_MALLOC_ENCODE(SubjectKeyIdentifier, data.data, data.length,
			   &si, &size, ret);
	if (ret) {
	    hx509_set_error_string(context, 0, ret, "Out of memory");
	    goto out;
	}
	if (size != data.length)
	    _hx509_abort("internal ASN.1 encoder error");
	ret = add_extension(context, tbsc, 0,
			    &asn1_oid_id_x509_ce_subjectKeyIdentifier,
			    &data);
	free(data.data);
	if (ret)
	    goto out;
    }

    /* Add BasicConstraints */
    {
	BasicConstraints bc;
	int aCA = 1;
	unsigned int path;

	memset(&bc, 0, sizeof(bc));

	if (tbs->flags.ca) {
	    bc.cA = &aCA;
	    if (tbs->pathLenConstraint >= 0) {
		path = tbs->pathLenConstraint;
		bc.pathLenConstraint = &path;
	    }
	}

	ASN1_MALLOC_ENCODE(BasicConstraints, data.data, data.length,
			   &bc, &size, ret);
	if (ret) {
	    hx509_set_error_string(context, 0, ret, "Out of memory");
	    goto out;
	}
	if (size != data.length)
	    _hx509_abort("internal ASN.1 encoder error");
	/* Critical if this is a CA */
	ret = add_extension(context, tbsc, tbs->flags.ca,
			    &asn1_oid_id_x509_ce_basicConstraints,
			    &data);
	free(data.data);
	if (ret)
	    goto out;
    }

    /* add Proxy */
    if (tbs->flags.proxy) {
	ProxyCertInfo info;

	memset(&info, 0, sizeof(info));

	if (tbs->pathLenConstraint >= 0) {
	    info.pCPathLenConstraint =
		malloc(sizeof(*info.pCPathLenConstraint));
	    if (info.pCPathLenConstraint == NULL) {
		ret = ENOMEM;
		hx509_set_error_string(context, 0, ret, "Out of memory");
		goto out;
	    }
	    *info.pCPathLenConstraint = tbs->pathLenConstraint;
	}

	ret = der_copy_oid(&asn1_oid_id_pkix_ppl_inheritAll,
			   &info.proxyPolicy.policyLanguage);
	if (ret) {
	    free_ProxyCertInfo(&info);
	    hx509_set_error_string(context, 0, ret, "Out of memory");
	    goto out;
	}

	ASN1_MALLOC_ENCODE(ProxyCertInfo, data.data, data.length,
			   &info, &size, ret);
	free_ProxyCertInfo(&info);
	if (ret) {
	    hx509_set_error_string(context, 0, ret, "Out of memory");
	    goto out;
	}
	if (size != data.length)
	    _hx509_abort("internal ASN.1 encoder error");
	ret = add_extension(context, tbsc, 0,
			    &asn1_oid_id_pkix_pe_proxyCertInfo,
			    &data);
	free(data.data);
	if (ret)
	    goto out;
    }

    if (tbs->crldp.len) {

	ASN1_MALLOC_ENCODE(CRLDistributionPoints, data.data, data.length,
			   &tbs->crldp, &size, ret);
	if (ret) {
	    hx509_set_error_string(context, 0, ret, "Out of memory");
	    goto out;
	}
	if (size != data.length)
	    _hx509_abort("internal ASN.1 encoder error");
	ret = add_extension(context, tbsc, FALSE,
			    &asn1_oid_id_x509_ce_cRLDistributionPoints,
			    &data);
	free(data.data);
	if (ret)
	    goto out;
    }

    ASN1_MALLOC_ENCODE(TBSCertificate, data.data, data.length,tbsc, &size, ret);
    if (ret) {
	hx509_set_error_string(context, 0, ret, "malloc out of memory");
	goto out;
    }
    if (data.length != size)
	_hx509_abort("internal ASN.1 encoder error");

    ret = _hx509_create_signature_bitstring(context,
					    signer,
					    sigalg,
					    &data,
					    &c.signatureAlgorithm,
					    &c.signatureValue);
    free(data.data);
    if (ret)
	goto out;

    ret = hx509_cert_init(context, &c, certificate);
    if (ret)
	goto out;

    free_Certificate(&c);

    return 0;

out:
    free_Certificate(&c);
    return ret;
}
Exemplo n.º 6
0
Arquivo: cms.c Projeto: 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;
}
Exemplo n.º 7
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;
}
Exemplo n.º 8
0
int
hx509_crl_sign(hx509_context context,
	       hx509_cert signer,
	       hx509_crl crl,
	       heim_octet_string *os)
{
    const AlgorithmIdentifier *sigalg = _hx509_crypto_default_sig_alg;
    CRLCertificateList c;
    size_t size;
    int ret;
    hx509_private_key signerkey;

    memset(&c, 0, sizeof(c));

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

    c.tbsCertList.version = malloc(sizeof(*c.tbsCertList.version));
    if (c.tbsCertList.version == NULL) {
	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
	return ENOMEM;
    }

    *c.tbsCertList.version = 1;

    ret = copy_AlgorithmIdentifier(sigalg, &c.tbsCertList.signature);
    if (ret) {
	hx509_clear_error_string(context);
	goto out;
    }

    ret = copy_Name(&_hx509_get_cert(signer)->tbsCertificate.issuer,
		    &c.tbsCertList.issuer);
    if (ret) {
	hx509_clear_error_string(context);
	goto out;
    }

    c.tbsCertList.thisUpdate.element = choice_Time_generalTime;
    c.tbsCertList.thisUpdate.u.generalTime = time(NULL) - 24 * 3600;

    c.tbsCertList.nextUpdate = malloc(sizeof(*c.tbsCertList.nextUpdate));
    if (c.tbsCertList.nextUpdate == NULL) {
	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
	ret = ENOMEM;
	goto out;
    }

    {
	time_t next = crl->expire;
	if (next == 0)
	    next = time(NULL) + 24 * 3600 * 365;

	c.tbsCertList.nextUpdate->element = choice_Time_generalTime;
	c.tbsCertList.nextUpdate->u.generalTime = next;
    }

    c.tbsCertList.revokedCertificates =
	calloc(1, sizeof(*c.tbsCertList.revokedCertificates));
    if (c.tbsCertList.revokedCertificates == NULL) {
	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
	ret = ENOMEM;
	goto out;
    }
    c.tbsCertList.crlExtensions = NULL;

    ret = hx509_certs_iter_f(context, crl->revoked, add_revoked, &c.tbsCertList);
    if (ret)
	goto out;

    /* if not revoked certs, remove OPTIONAL entry */
    if (c.tbsCertList.revokedCertificates->len == 0) {
	free(c.tbsCertList.revokedCertificates);
	c.tbsCertList.revokedCertificates = NULL;
    }

    ASN1_MALLOC_ENCODE(TBSCRLCertList, os->data, os->length,
		       &c.tbsCertList, &size, ret);
    if (ret) {
	hx509_set_error_string(context, 0, ret, "failed to encode tbsCRL");
	goto out;
    }
    if (size != os->length)
	_hx509_abort("internal ASN.1 encoder error");


    ret = _hx509_create_signature_bitstring(context,
					    signerkey,
					    sigalg,
					    os,
					    &c.signatureAlgorithm,
					    &c.signatureValue);
    free(os->data);
    if (ret) {
	hx509_set_error_string(context, 0, ret, "Failed to sign CRL");
	goto out;
    }

    ASN1_MALLOC_ENCODE(CRLCertificateList, os->data, os->length,
		       &c, &size, ret);
    if (ret) {
	hx509_set_error_string(context, 0, ret, "failed to encode CRL");
	goto out;
    }
    if (size != os->length)
	_hx509_abort("internal ASN.1 encoder error");

    free_CRLCertificateList(&c);

    return 0;

out:
    free_CRLCertificateList(&c);
    return ret;
}
Exemplo n.º 9
0
int
hx509_cms_create_signed(hx509_context context,
			int flags,
			const heim_oid *eContentType,
			const void *data, size_t length,
			const AlgorithmIdentifier *digest_alg,
			hx509_certs certs,
			hx509_peer_info peer,
			hx509_certs anchors,
			hx509_certs pool,
			heim_octet_string *signed_data)
{
    unsigned int i;
    hx509_name name;
    int ret;
    size_t size;
    struct sigctx sigctx;

    memset(&sigctx, 0, sizeof(sigctx));
    memset(&name, 0, sizeof(name));

    if (eContentType == NULL)
	eContentType = &asn1_oid_id_pkcs7_data;

    sigctx.digest_alg = digest_alg;
    sigctx.content.data = rk_UNCONST(data);
    sigctx.content.length = length;
    sigctx.eContentType = eContentType;
    sigctx.peer = peer;
    /**
     * Use HX509_CMS_SIGNATURE_ID_NAME to preferred use of issuer name
     * and serial number if possible. Otherwise subject key identifier
     * will preferred.
     */
    if (flags & HX509_CMS_SIGNATURE_ID_NAME)
	sigctx.cmsidflag = CMS_ID_NAME;
    else
	sigctx.cmsidflag = CMS_ID_SKI;

    ret = hx509_certs_init(context, "MEMORY:certs", 0, NULL, &sigctx.certs);
    if (ret)
	return ret;

    sigctx.anchors = anchors;
    sigctx.pool = pool;

    sigctx.sd.version = CMSVersion_v3;

    der_copy_oid(eContentType, &sigctx.sd.encapContentInfo.eContentType);

    /**
     * Use HX509_CMS_SIGNATURE_DETACHED to create detached signatures.
     */
    if ((flags & HX509_CMS_SIGNATURE_DETACHED) == 0) {
	ALLOC(sigctx.sd.encapContentInfo.eContent, 1);
	if (sigctx.sd.encapContentInfo.eContent == NULL) {
	    hx509_clear_error_string(context);
	    ret = ENOMEM;
	    goto out;
	}
	
	sigctx.sd.encapContentInfo.eContent->data = malloc(length);
	if (sigctx.sd.encapContentInfo.eContent->data == NULL) {
	    hx509_clear_error_string(context);
	    ret = ENOMEM;
	    goto out;
	}
	memcpy(sigctx.sd.encapContentInfo.eContent->data, data, length);
	sigctx.sd.encapContentInfo.eContent->length = length;
    }

    /**
     * Use HX509_CMS_SIGNATURE_NO_SIGNER to create no sigInfo (no
     * signatures).
     */
    if ((flags & HX509_CMS_SIGNATURE_NO_SIGNER) == 0) {
	ret = hx509_certs_iter(context, certs, sig_process, &sigctx);
	if (ret)
	    goto out;
    }

    if (sigctx.sd.signerInfos.len) {
	ALLOC_SEQ(&sigctx.sd.digestAlgorithms, sigctx.sd.signerInfos.len);
	if (sigctx.sd.digestAlgorithms.val == NULL) {
	    ret = ENOMEM;
	    hx509_clear_error_string(context);
	    goto out;
	}
	
	/* XXX remove dups */
	for (i = 0; i < sigctx.sd.signerInfos.len; i++) {
	    AlgorithmIdentifier *di =
		&sigctx.sd.signerInfos.val[i].digestAlgorithm;
	    ret = copy_AlgorithmIdentifier(di,
					   &sigctx.sd.digestAlgorithms.val[i]);
	    if (ret) {
		hx509_clear_error_string(context);
		goto out;
	    }
	}
    }

    if (sigctx.certs) {
	ALLOC(sigctx.sd.certificates, 1);
	if (sigctx.sd.certificates == NULL) {
	    hx509_clear_error_string(context);
	    ret = ENOMEM;
	    goto out;
	}

	ret = hx509_certs_iter(context, sigctx.certs, cert_process, &sigctx);
	if (ret)
	    goto out;
    }

    ASN1_MALLOC_ENCODE(SignedData,
		       signed_data->data, signed_data->length,
		       &sigctx.sd, &size, ret);
    if (ret) {
	hx509_clear_error_string(context);
	goto out;
    }
    if (signed_data->length != size)
	_hx509_abort("internal ASN.1 encoder error");

out:
    hx509_certs_free(&sigctx.certs);
    free_SignedData(&sigctx.sd);

    return ret;
}