/** * Builds a transId attribute */ chunk_t scep_transId_attribute(chunk_t transID) { return asn1_wrap(ASN1_SEQUENCE, "cm" , ASN1_transId_oid , asn1_wrap(ASN1_SET, "m" , asn1_simple_object(ASN1_PRINTABLESTRING, transID) ) ); }
/* * build holder */ static chunk_t build_holder(void) { return asn1_wrap(ASN1_SEQUENCE, "mm" , asn1_wrap(ASN1_CONTEXT_C_0, "mm" , build_directoryName(ASN1_SEQUENCE, user->issuer) , asn1_simple_object(ASN1_INTEGER, user->serialNumber) ) , build_directoryName(ASN1_CONTEXT_C_1, user->subject)); }
/** * create a signed pkcs7 contentInfo object */ chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes, certificate_t *cert, int digest_alg, private_key_t *key) { contentInfo_t pkcs7Data, signedData; chunk_t authenticatedAttributes = chunk_empty; chunk_t encryptedDigest = chunk_empty; chunk_t signerInfo, cInfo, signature, encoding = chunk_empty;; signature_scheme_t scheme = signature_scheme_from_oid(digest_alg); if (attributes.ptr) { if (key->sign(key, scheme, attributes, &signature)) { encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", signature); authenticatedAttributes = chunk_clone(attributes); *authenticatedAttributes.ptr = ASN1_CONTEXT_C_0; } } else if (data.ptr) { if (key->sign(key, scheme, data, &signature)) { encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", signature); } } signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmmmmm" , ASN1_INTEGER_1 , pkcs7_build_issuerAndSerialNumber(cert) , asn1_algorithmIdentifier(digest_alg) , authenticatedAttributes , asn1_algorithmIdentifier(OID_RSA_ENCRYPTION) , encryptedDigest); pkcs7Data.type = OID_PKCS7_DATA; pkcs7Data.content = (data.ptr == NULL)? chunk_empty : asn1_simple_object(ASN1_OCTET_STRING, data); cert->get_encoding(cert, CERT_ASN1_DER, &encoding); signedData.type = OID_PKCS7_SIGNED_DATA; signedData.content = asn1_wrap(ASN1_SEQUENCE, "cmmmm" , ASN1_INTEGER_1 , asn1_wrap(ASN1_SET, "m", asn1_algorithmIdentifier(digest_alg)) , pkcs7_build_contentInfo(&pkcs7Data) , asn1_wrap(ASN1_CONTEXT_C_0, "m", encoding) , asn1_wrap(ASN1_SET, "m", signerInfo)); cInfo = pkcs7_build_contentInfo(&signedData); DBG3(DBG_LIB, "signedData %B", &cInfo); free(pkcs7Data.content.ptr); free(signedData.content.ptr); return cInfo; }
/* * build attributeCertificateInfo */ static chunk_t build_attr_cert_info(void) { return asn1_wrap(ASN1_SEQUENCE, "cmmcmmmm" , ASN1_INTEGER_1 , build_holder() , build_v2_form() , ASN1_sha1WithRSA_id , asn1_simple_object(ASN1_INTEGER, serial) , build_attr_cert_validity() , build_attributes() , build_extensions()); }
/** * Builds a messageType attribute */ chunk_t scep_messageType_attribute(scep_msg_t m) { chunk_t msgType = { (u_char*)msgType_values[m], strlen(msgType_values[m]) }; return asn1_wrap(ASN1_SEQUENCE, "cm" , ASN1_messageType_oid , asn1_wrap(ASN1_SET, "m" , asn1_simple_object(ASN1_PRINTABLESTRING, msgType) ) ); }
END_TEST /******************************************************************************* * simple_object */ START_TEST(test_asn1_simple_object) { chunk_t a = chunk_empty; chunk_t b = chunk_from_chars(0x04, 0x05, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5); chunk_t c = chunk_from_chars(0xa1, 0xa2, 0xa3, 0xa4, 0xa5); a = asn1_simple_object(0x04, c); ck_assert(chunk_equals(a, b)); chunk_free(&a); }
/* * builds a senderNonce attribute */ chunk_t scep_senderNonce_attribute(void) { const size_t nonce_len = 16; u_char nonce_buf[nonce_len]; chunk_t senderNonce = { nonce_buf, nonce_len }; get_rnd_bytes(nonce_buf, nonce_len); return asn1_wrap(ASN1_SEQUENCE, "cm" , ASN1_senderNonce_oid , asn1_wrap(ASN1_SET, "m" , asn1_simple_object(ASN1_OCTET_STRING, senderNonce) ) ); }
/** * Builds a senderNonce attribute */ chunk_t scep_senderNonce_attribute(void) { const size_t nonce_len = 16; u_char nonce_buf[nonce_len]; chunk_t senderNonce = { nonce_buf, nonce_len }; rng_t *rng; rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); rng->get_bytes(rng, nonce_len, nonce_buf); rng->destroy(rng); return asn1_wrap(ASN1_SEQUENCE, "cm" , ASN1_senderNonce_oid , asn1_wrap(ASN1_SET, "m" , asn1_simple_object(ASN1_OCTET_STRING, senderNonce) ) ); }
/* * build attributes */ static chunk_t build_ietfAttributes(ietfAttrList_t *list) { chunk_t ietfAttributes; ietfAttrList_t *item = list; size_t size = 0; u_char *pos; /* precalculate the total size of all values */ while (item != NULL) { size_t len = item->attr->value.len; size += 1 + (len > 0) + (len >= 128) + (len >= 256) + (len >= 65536) + len; item = item->next; } pos = build_asn1_object(&ietfAttributes, ASN1_SEQUENCE, size); while (list != NULL) { ietfAttr_t *attr = list->attr; asn1_t type = ASN1_NULL; switch (attr->kind) { case IETF_ATTRIBUTE_OCTETS: type = ASN1_OCTET_STRING; break; case IETF_ATTRIBUTE_STRING: type = ASN1_UTF8STRING; break; case IETF_ATTRIBUTE_OID: type = ASN1_OID; break; } mv_chunk(&pos, asn1_simple_object(type, attr->value)); list = list->next; } return asn1_wrap(ASN1_SEQUENCE, "m", ietfAttributes); }
/* * Defined in header. */ chunk_t asn1_algorithmIdentifier(int oid) { chunk_t parameters; /* some algorithmIdentifiers have a NULL parameters field and some do not */ switch (oid) { case OID_ECDSA_WITH_SHA1: case OID_ECDSA_WITH_SHA224: case OID_ECDSA_WITH_SHA256: case OID_ECDSA_WITH_SHA384: case OID_ECDSA_WITH_SHA512: parameters = chunk_empty; break; default: parameters = asn1_simple_object(ASN1_NULL, chunk_empty); break; } return asn1_wrap(ASN1_SEQUENCE, "mm", asn1_build_known_oid(oid), parameters); }
/** * create a symmetrically encrypted pkcs7 contentInfo object */ chunk_t pkcs7_build_envelopedData(chunk_t data, certificate_t *cert, int enc_alg) { encryption_algorithm_t alg; size_t alg_key_size; chunk_t symmetricKey, protectedKey, iv, in, out; crypter_t *crypter; alg = encryption_algorithm_from_oid(enc_alg, &alg_key_size); crypter = lib->crypto->create_crypter(lib->crypto, alg, alg_key_size/BITS_PER_BYTE); if (crypter == NULL) { DBG1(DBG_LIB, "crypter for %N not available", encryption_algorithm_names, alg); return chunk_empty; } /* generate a true random symmetric encryption key and a pseudo-random iv */ { rng_t *rng; rng = lib->crypto->create_rng(lib->crypto, RNG_TRUE); rng->allocate_bytes(rng, crypter->get_key_size(crypter), &symmetricKey); DBG4(DBG_LIB, "symmetric encryption key %B", &symmetricKey); rng->destroy(rng); rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); rng->allocate_bytes(rng, crypter->get_iv_size(crypter), &iv); DBG4(DBG_LIB, "initialization vector: %B", &iv); rng->destroy(rng); } /* pad the data to a multiple of the block size */ { size_t block_size = crypter->get_block_size(crypter); size_t padding = block_size - data.len % block_size; in.len = data.len + padding; in.ptr = malloc(in.len); DBG2(DBG_LIB, "padding %u bytes of data to multiple block size of %u bytes", data.len, in.len); /* copy data */ memcpy(in.ptr, data.ptr, data.len); /* append padding */ memset(in.ptr + data.len, padding, padding); } DBG3(DBG_LIB, "padded unencrypted data %B", &in); /* symmetric encryption of data object */ crypter->set_key(crypter, symmetricKey); crypter->encrypt(crypter, in, iv, &out); crypter->destroy(crypter); chunk_clear(&in); DBG3(DBG_LIB, "encrypted data %B", &out); /* protect symmetric key by public key encryption */ { public_key_t *key = cert->get_public_key(cert); if (key == NULL) { DBG1(DBG_LIB, "public key not found in encryption certificate"); chunk_clear(&symmetricKey); chunk_free(&iv); chunk_free(&out); return chunk_empty; } key->encrypt(key, ENCRYPT_RSA_PKCS1, symmetricKey, &protectedKey); key->destroy(key); } /* build pkcs7 enveloped data object */ { chunk_t contentEncryptionAlgorithm = asn1_wrap(ASN1_SEQUENCE, "mm" , asn1_build_known_oid(enc_alg) , asn1_simple_object(ASN1_OCTET_STRING, iv)); chunk_t encryptedContentInfo = asn1_wrap(ASN1_SEQUENCE, "mmm" , asn1_build_known_oid(OID_PKCS7_DATA) , contentEncryptionAlgorithm , asn1_wrap(ASN1_CONTEXT_S_0, "m", out)); chunk_t encryptedKey = asn1_wrap(ASN1_OCTET_STRING, "m" , protectedKey); chunk_t recipientInfo = asn1_wrap(ASN1_SEQUENCE, "cmmm" , ASN1_INTEGER_0 , pkcs7_build_issuerAndSerialNumber(cert) , asn1_algorithmIdentifier(OID_RSA_ENCRYPTION) , encryptedKey); chunk_t cInfo; contentInfo_t envelopedData; envelopedData.type = OID_PKCS7_ENVELOPED_DATA; envelopedData.content = asn1_wrap(ASN1_SEQUENCE, "cmm" , ASN1_INTEGER_0 , asn1_wrap(ASN1_SET, "m", recipientInfo) , encryptedContentInfo); cInfo = pkcs7_build_contentInfo(&envelopedData); DBG3(DBG_LIB, "envelopedData %B", &cInfo); chunk_free(&envelopedData.content); chunk_free(&iv); chunk_clear(&symmetricKey); return cInfo; } }
/* * build directoryName */ static chunk_t build_directoryName(asn1_t tag, chunk_t name) { return asn1_wrap(tag, "m" , asn1_simple_object(ASN1_CONTEXT_C_4, name)); }