/** * load the credential from a blob */ static void *load_from_blob(chunk_t blob, credential_type_t type, int subtype, chunk_t(*cb)(void*,int), void *cb_data, x509_flag_t flags) { void *cred = NULL; bool pgp = FALSE; blob = chunk_clone(blob); if (!is_asn1(blob)) { if (pem_to_bin(&blob, cb, cb_data, &pgp) != SUCCESS) { chunk_clear(&blob); return NULL; } if (pgp && type == CRED_PRIVATE_KEY) { /* PGP encoded keys are parsed with a KEY_ANY key type, as it * can contain any type of key. However, ipsec.secrets uses * RSA for PGP keys, which is actually wrong. */ subtype = KEY_ANY; } } /* if CERT_ANY is given, ASN1 encoded blob is handled as X509 */ if (type == CRED_CERTIFICATE && subtype == CERT_ANY) { subtype = pgp ? CERT_GPG : CERT_X509; } cred = lib->creds->create(lib->creds, type, subtype, pgp ? BUILD_BLOB_PGP : BUILD_BLOB_ASN1_DER, blob, flags ? BUILD_X509_FLAG : BUILD_END, flags, BUILD_END); chunk_clear(&blob); return cred; }
/** * Try to decrypt the given blob with multiple passwords using the given * pkcs5 object. */ static private_key_t *decrypt_private_key(pkcs5_t *pkcs5, chunk_t blob) { enumerator_t *enumerator; shared_key_t *shared; private_key_t *private_key = NULL; enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr, SHARED_PRIVATE_KEY_PASS, NULL, NULL); while (enumerator->enumerate(enumerator, &shared, NULL, NULL)) { chunk_t decrypted; if (!pkcs5->decrypt(pkcs5, shared->get_key(shared), blob, &decrypted)) { continue; } private_key = parse_private_key(decrypted); if (private_key) { chunk_clear(&decrypted); break; } chunk_free(&decrypted); } enumerator->destroy(enumerator); return private_key; }
/* * Described in header */ bool botan_dh_key_derivation(botan_privkey_t key, chunk_t pub, chunk_t *secret) { botan_pk_op_ka_t ka; if (botan_pk_op_key_agreement_create(&ka, key, "Raw", 0)) { return FALSE; } if (botan_pk_op_key_agreement_size(ka, &secret->len)) { botan_pk_op_key_agreement_destroy(ka); return FALSE; } *secret = chunk_alloc(secret->len); if (botan_pk_op_key_agreement(ka, secret->ptr, &secret->len, pub.ptr, pub.len, NULL, 0)) { chunk_clear(secret); botan_pk_op_key_agreement_destroy(ka); return FALSE; } botan_pk_op_key_agreement_destroy(ka); return TRUE; }
static void chunk_flush (GstAdapter *adapter, Chunk *chunk) { g_return_if_fail (chunk->available == chunk->length); gst_adapter_flush (adapter, chunk->length); chunk_clear (chunk); }
/* * Described in header. */ bool rng_allocate_bytes_not_zero(rng_t *rng, size_t len, chunk_t *chunk, bool all) { *chunk = chunk_alloc(len); if (!rng_get_bytes_not_zero(rng, len, chunk->ptr, all)) { chunk_clear(chunk); return FALSE; } return TRUE; }
END_TEST START_TEST(test_newhope_ke_wrong) { chunk_t i_msg, r_msg, i_shared_secret, r_shared_secret; diffie_hellman_t *i_nh, *r_nh; i_nh = lib->crypto->create_dh(lib->crypto, NH_128_BIT); ck_assert(i_nh != NULL); ck_assert(i_nh->get_my_public_value(i_nh, &i_msg)); r_nh = lib->crypto->create_dh(lib->crypto, NH_128_BIT); ck_assert(r_nh != NULL); ck_assert(r_nh->set_other_public_value(r_nh, i_msg)); ck_assert(r_nh->get_my_public_value(r_nh, &r_msg)); /* destroy 1st instance of i_nh */ i_nh->destroy(i_nh); chunk_free(&i_msg); /* create 2nd instance of i_nh */ i_nh = lib->crypto->create_dh(lib->crypto, NH_128_BIT); ck_assert(i_nh != NULL); ck_assert(i_nh->get_my_public_value(i_nh, &i_msg)); ck_assert(i_nh->set_other_public_value(i_nh, r_msg)); ck_assert(r_nh->get_shared_secret(r_nh, &r_shared_secret)); ck_assert(i_nh->get_shared_secret(i_nh, &i_shared_secret)); ck_assert(!chunk_equals(i_shared_secret, r_shared_secret)); /* cleanup */ chunk_clear(&i_shared_secret); chunk_clear(&r_shared_secret); chunk_free(&i_msg); chunk_free(&r_msg); i_nh->destroy(i_nh); r_nh->destroy(r_nh); }
END_TEST /******************************************************************************* * clear */ START_TEST(test_chunk_clear) { chunk_t chunk; u_char *ptr; int i; bool cleared = TRUE; chunk = chunk_empty; chunk_clear(&chunk); chunk_free(&chunk); chunk = chunk_alloc(64); ptr = chunk.ptr; for (i = 0; i < 64; i++) { chunk.ptr[i] = i; } chunk_clear(&chunk); /* check memory area of freed chunk. We can't use ck_assert() for this * test directly, as it might allocate data at the freed area. */ for (i = 0; i < 64; i++) { if (ptr[i] != 0 && ptr[i] == i) { cleared = FALSE; break; } } assert_chunk_empty(chunk); ck_assert(cleared); }
static void gst_smfdec_reset (GstSmfdec *dec) { gst_adapter_clear (dec->adapter); chunk_clear (&dec->chunk); dec->format = 0; dec->start = 0; dec->status = 0; dec->division = 1; dec->ticks = 0; dec->buf_start = 0; dec->buf_num=1024; dec->buf_denom=44100; dec->buf_sent = 0; gst_smfdec_set_tempo (dec, 480000); }
/** * Described in header. */ chunk_t chunk_create_cat(u_char *ptr, const char* mode, ...) { va_list chunks; chunk_t construct = chunk_create(ptr, 0); va_start(chunks, mode); while (TRUE) { bool free_chunk = FALSE, clear_chunk = FALSE; chunk_t ch; switch (*mode++) { case 's': clear_chunk = TRUE; /* FALL */ case 'm': free_chunk = TRUE; /* FALL */ case 'c': ch = va_arg(chunks, chunk_t); memcpy(ptr, ch.ptr, ch.len); ptr += ch.len; construct.len += ch.len; if (clear_chunk) { chunk_clear(&ch); } else if (free_chunk) { free(ch.ptr); } continue; default: break; } break; } va_end(chunks); return construct; }
/** * See header. */ bool pem_encoder_encode(cred_encoding_type_t type, chunk_t *encoding, va_list args) { chunk_t asn1; char *label; u_char *pos; size_t len, written, pem_chars, pem_lines; chunk_t n, e, d, p, q, exp1, exp2, coeff, to_free = chunk_empty; switch (type) { case PUBKEY_PEM: label ="PUBLIC KEY"; /* direct PKCS#1 PEM encoding */ if (cred_encoding_args(args, CRED_PART_RSA_PUB_ASN1_DER, &asn1, CRED_PART_END) || cred_encoding_args(args, CRED_PART_ECDSA_PUB_ASN1_DER, &asn1, CRED_PART_END) || cred_encoding_args(args, CRED_PART_EDDSA_PUB_ASN1_DER, &asn1, CRED_PART_END) || cred_encoding_args(args, CRED_PART_BLISS_PUB_ASN1_DER, &asn1, CRED_PART_END)) { break; } /* indirect PEM encoding from components */ if (cred_encoding_args(args, CRED_PART_RSA_MODULUS, &n, CRED_PART_RSA_PUB_EXP, &e, CRED_PART_END)) { if (lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER, NULL, &asn1, CRED_PART_RSA_MODULUS, n, CRED_PART_RSA_PUB_EXP, e, CRED_PART_END)) { to_free = asn1; break; } } return FALSE; case PRIVKEY_PEM: label ="RSA PRIVATE KEY"; /* direct PKCS#1 PEM encoding */ if (cred_encoding_args(args, CRED_PART_RSA_PRIV_ASN1_DER, &asn1, CRED_PART_END)) { break; } /* indirect PEM encoding from components */ if (cred_encoding_args(args, CRED_PART_RSA_MODULUS, &n, CRED_PART_RSA_PUB_EXP, &e, CRED_PART_RSA_PRIV_EXP, &d, CRED_PART_RSA_PRIME1, &p, CRED_PART_RSA_PRIME2, &q, CRED_PART_RSA_EXP1, &exp1, CRED_PART_RSA_EXP2, &exp2, CRED_PART_RSA_COEFF, &coeff, CRED_PART_END)) { if (lib->encoding->encode(lib->encoding, PRIVKEY_ASN1_DER, NULL, &asn1, CRED_PART_RSA_MODULUS, n, CRED_PART_RSA_PUB_EXP, e, CRED_PART_RSA_PRIV_EXP, d, CRED_PART_RSA_PRIME1, p, CRED_PART_RSA_PRIME2, q, CRED_PART_RSA_EXP1, exp1, CRED_PART_RSA_EXP2, exp2, CRED_PART_RSA_COEFF, coeff, CRED_PART_END)) { to_free = asn1; break; } } if (cred_encoding_args(args, CRED_PART_ECDSA_PRIV_ASN1_DER, &asn1, CRED_PART_END)) { label ="EC PRIVATE KEY"; break; } if (cred_encoding_args(args, CRED_PART_BLISS_PRIV_ASN1_DER, &asn1, CRED_PART_END)) { label ="BLISS PRIVATE KEY"; break; } if (cred_encoding_args(args, CRED_PART_EDDSA_PRIV_ASN1_DER, &asn1, CRED_PART_END)) { label ="PRIVATE KEY"; break; } return FALSE; case CERT_PEM: if (cred_encoding_args(args, CRED_PART_X509_ASN1_DER, &asn1, CRED_PART_END)) { /* PEM encode x509 certificate */ label = "CERTIFICATE"; break; } if (cred_encoding_args(args, CRED_PART_X509_CRL_ASN1_DER, &asn1, CRED_PART_END)) { /* PEM encode CRL */ label = "X509 CRL"; break; } if (cred_encoding_args(args, CRED_PART_PKCS10_ASN1_DER, &asn1, CRED_PART_END)) { /* PEM encode PKCS10 certificate reqeuest */ label = "CERTIFICATE REQUEST"; break; } if (cred_encoding_args(args, CRED_PART_X509_AC_ASN1_DER, &asn1, CRED_PART_END)) { label = "ATTRIBUTE CERTIFICATE"; break; } default: return FALSE; } /* compute and allocate maximum size of PEM object */ pem_chars = 4 * ((asn1.len + 2) / 3); pem_lines = (asn1.len + BYTES_PER_LINE - 1) / BYTES_PER_LINE; *encoding = chunk_alloc(5 + 2*(6 + strlen(label) + 6) + 3 + pem_chars + pem_lines); pos = encoding->ptr; len = encoding->len; /* write PEM header */ written = snprintf(pos, len, "-----BEGIN %s-----\n", label); pos += written; len -= written; /* write PEM body */ while (pem_lines--) { chunk_t asn1_line, pem_line; asn1_line = chunk_create(asn1.ptr, min(asn1.len, BYTES_PER_LINE)); asn1.ptr += asn1_line.len; asn1.len -= asn1_line.len; pem_line = chunk_to_base64(asn1_line, pos); pos += pem_line.len; len -= pem_line.len; *pos = '\n'; pos++; len--; } chunk_clear(&to_free); /* write PEM trailer */ written = snprintf(pos, len, "-----END %s-----", label); pos += written; len -= written; /* replace termination null character with newline */ *pos = '\n'; pos++; len--; /* compute effective length of PEM object */ encoding->len = pos - encoding->ptr; return TRUE; }
/** * 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; } }
/** * Parse a PKCS#7 envelopedData object */ bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data, chunk_t serialNumber, private_key_t *key) { asn1_parser_t *parser; chunk_t object; chunk_t iv = chunk_empty; chunk_t symmetric_key = chunk_empty; chunk_t encrypted_content = chunk_empty; crypter_t *crypter = NULL; int enc_alg = OID_UNKNOWN; int content_enc_alg = OID_UNKNOWN; int version; int objectID; bool success = FALSE; contentInfo_t cInfo = empty_contentInfo; *data = chunk_empty; if (!pkcs7_parse_contentInfo(blob, 0, &cInfo)) { goto failed; } if (cInfo.type != OID_PKCS7_ENVELOPED_DATA) { DBG1(DBG_LIB, "pkcs7 content type is not envelopedData"); goto failed; } parser = asn1_parser_create(envelopedDataObjects, cInfo.content); parser->set_top_level(parser, 2); while (parser->iterate(parser, &objectID, &object)) { u_int level = parser->get_level(parser); switch (objectID) { case PKCS7_ENVELOPED_VERSION: version = object.len ? (int)*object.ptr : 0; DBG2(DBG_LIB, " v%d", version); if (version != 0) { DBG1(DBG_LIB, "envelopedData version is not 0"); goto end; } break; case PKCS7_RECIPIENT_INFO_VERSION: version = object.len ? (int)*object.ptr : 0; DBG2(DBG_LIB, " v%d", version); if (version != 0) { DBG1(DBG_LIB, "recipient info version is not 0"); goto end; } break; case PKCS7_ISSUER: { identification_t *issuer = identification_create_from_encoding( ID_DER_ASN1_DN, object); DBG2(DBG_LIB, " \"%Y\"", issuer); issuer->destroy(issuer); break; } case PKCS7_SERIAL_NUMBER: if (!chunk_equals(serialNumber, object)) { DBG1(DBG_LIB, "serial numbers do not match"); goto end; } break; case PKCS7_ENCRYPTION_ALG: enc_alg = asn1_parse_algorithmIdentifier(object, level, NULL); if (enc_alg != OID_RSA_ENCRYPTION) { DBG1(DBG_LIB, "only rsa encryption supported"); goto end; } break; case PKCS7_ENCRYPTED_KEY: if (!key->decrypt(key, ENCRYPT_RSA_PKCS1, object, &symmetric_key)) { DBG1(DBG_LIB, "symmetric key could not be decrypted with rsa"); goto end; } DBG4(DBG_LIB, "symmetric key %B", &symmetric_key); break; case PKCS7_CONTENT_TYPE: if (asn1_known_oid(object) != OID_PKCS7_DATA) { DBG1(DBG_LIB, "encrypted content not of type pkcs7 data"); goto end; } break; case PKCS7_CONTENT_ENC_ALGORITHM: content_enc_alg = asn1_parse_algorithmIdentifier(object, level, &iv); if (content_enc_alg == OID_UNKNOWN) { DBG1(DBG_LIB, "unknown content encryption algorithm"); goto end; } if (!asn1_parse_simple_object(&iv, ASN1_OCTET_STRING, level+1, "IV")) { DBG1(DBG_LIB, "IV could not be parsed"); goto end; } break; case PKCS7_ENCRYPTED_CONTENT: encrypted_content = object; break; } } success = parser->success(parser); end: parser->destroy(parser); if (!success) { goto failed; } success = FALSE; /* decrypt the content */ { encryption_algorithm_t alg; size_t key_size; crypter_t *crypter; alg = encryption_algorithm_from_oid(content_enc_alg, &key_size); if (alg == ENCR_UNDEFINED) { DBG1(DBG_LIB, "unsupported content encryption algorithm"); goto failed; } crypter = lib->crypto->create_crypter(lib->crypto, alg, key_size); if (crypter == NULL) { DBG1(DBG_LIB, "crypter %N not available", encryption_algorithm_names, alg); goto failed; } if (symmetric_key.len != crypter->get_key_size(crypter)) { DBG1(DBG_LIB, "symmetric key length %d is wrong", symmetric_key.len); goto failed; } if (iv.len != crypter->get_iv_size(crypter)) { DBG1(DBG_LIB, "IV length %d is wrong", iv.len); goto failed; } crypter->set_key(crypter, symmetric_key); crypter->decrypt(crypter, encrypted_content, iv, data); DBG4(DBG_LIB, "decrypted content with padding: %B", data); } /* remove the padding */ { u_char *pos = data->ptr + data->len - 1; u_char pattern = *pos; size_t padding = pattern; if (padding > data->len) { DBG1(DBG_LIB, "padding greater than data length"); goto failed; } data->len -= padding; while (padding-- > 0) { if (*pos-- != pattern) { DBG1(DBG_LIB, "wrong padding pattern"); goto failed; } } } success = TRUE; failed: DESTROY_IF(crypter); chunk_clear(&symmetric_key); if (!success) { free(data->ptr); } return success; }
static GstFlowReturn gst_smfdec_chain (GstPad * pad, GstBuffer * data) { GstSmfdec *dec = GST_SMFDEC (gst_pad_get_parent (pad)); gint i, ticks; guint len, midi_len; /* we must be negotiated */ g_assert ( dec != NULL ); g_assert (dec->buf_denom > 0); gst_adapter_push (dec->adapter, GST_BUFFER (data)); if (dec->chunk.fourcc) { chunk_ensure (dec->adapter, &dec->chunk, 0); } while (dec->chunk.fourcc || get_next_chunk (dec->adapter, &dec->chunk)) { switch (dec->chunk.fourcc) { case GST_MAKE_FOURCC ('M', 'T', 'h', 'd'): if (dec->format) { GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("got a header chunk while already initialized")); goto error; } if (dec->chunk.length != 6) { GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("header chunk %d bytes long, not 6", (int) dec->chunk.length)); goto error; } if (!chunk_ensure (dec->adapter, &dec->chunk, 6)) goto out; /* we add one, so we can use 0 for uninitialized */ dec->format = GST_READ_UINT16_BE (dec->chunk.data) + 1; if (dec->format > 2) g_warning ("I have no clue if midi format %u works", dec->format - 1); dec->tracks_missing = GST_READ_UINT16_BE (dec->chunk.data + 2); //g_assert (dec->tracks_missing == 1); /* ignore the number of track atoms */ i = (gint16) GST_READ_UINT16_BE (dec->chunk.data + 4); if (i < 0) { GST_ELEMENT_ERROR (dec, STREAM, NOT_IMPLEMENTED, (NULL), ("can't handle smpte timing")); goto error; } else { dec->start = 0; dec->division = i; } chunk_flush (dec->adapter, &dec->chunk); break; case GST_MAKE_FOURCC ('M', 'T', 'r', 'k'): if (dec->format == 0) { GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("got a track chunk while not yet initialized")); goto error; } /* figure out if we have enough data */ ticks = gst_midi_data_parse_varlen (dec->chunk.data, dec->chunk.available, &len); if (ticks == -1) goto out; if (ticks == -2) { GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("invalid delta time value")); goto error; } midi_len = gst_midi_data_get_length (dec->chunk.data + len, dec->chunk.available - len, dec->status); if (midi_len == 0) goto out; /* we have enough data, process */ dec->ticks += ticks; //g_print ("got %u ticks, now %u\n", ticks, dec->ticks); if (dec->chunk.data[len] & 0x80) { dec->status = dec->chunk.data[len]; len++; midi_len--; } if (dec->status == 0xFF) { if (!gst_smfdec_meta_event (dec, dec->chunk.data + len, midi_len)) goto error; } else { gst_smfdec_buffer_append (dec, dec->status, dec->chunk.data + len, midi_len); } chunk_skip (dec->adapter, &dec->chunk, len + midi_len); if (dec->chunk.length == 0) chunk_clear (&dec->chunk); break; default: goto out; } } out: gst_object_unref(dec); return GST_FLOW_OK;; error: gst_smfdec_reset (dec); return GST_FLOW_ERROR; }