END_TEST /******************************************************************************* * bitstring */ START_TEST(test_asn1_bitstring) { chunk_t a = chunk_empty; chunk_t b = chunk_from_chars(0x03, 0x05, 0x00, 0xa1, 0xa2, 0xa3, 0xa4); chunk_t c = chunk_from_chars(0xa1, 0xa2, 0xa3, 0xa4); chunk_t d = chunk_clone(c); a = asn1_bitstring("c", c); ck_assert(chunk_equals(a, b)); chunk_free(&a); a = asn1_bitstring("m", d); ck_assert(chunk_equals(a, b)); chunk_free(&a); }
/** * Generate a transaction id as the MD5 hash of an public key * the transaction id is also used as a unique serial number */ void scep_generate_transaction_id(public_key_t *key, chunk_t *transID, chunk_t *serialNumber) { chunk_t digest = chunk_alloca(HASH_SIZE_MD5); chunk_t keyEncoding = chunk_empty, keyInfo; hasher_t *hasher; bool msb_set; u_char *pos; key->get_encoding(key, PUBKEY_ASN1_DER, &keyEncoding); keyInfo = asn1_wrap(ASN1_SEQUENCE, "mm", asn1_algorithmIdentifier(OID_RSA_ENCRYPTION), asn1_bitstring("m", keyEncoding)); hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5); if (!hasher || !hasher->get_hash(hasher, keyInfo, digest.ptr)) { memset(digest.ptr, 0, digest.len); } DESTROY_IF(hasher); free(keyInfo.ptr); /* is the most significant bit of the digest set? */ msb_set = (*digest.ptr & 0x80) == 0x80; /* allocate space for the serialNumber */ serialNumber->len = msb_set + digest.len; serialNumber->ptr = malloc(serialNumber->len); /* the serial number as the two's complement of the digest */ pos = serialNumber->ptr; if (msb_set) { *pos++ = 0x00; } memcpy(pos, digest.ptr, digest.len); /* the transaction id is the serial number in hex format */ *transID = chunk_to_hex(digest, NULL, TRUE); }
/** * Load a generic public key from an SSH key blob */ static sshkey_public_key_t *parse_public_key(chunk_t blob) { bio_reader_t *reader; chunk_t format; reader = bio_reader_create(blob); if (!reader->read_data32(reader, &format)) { DBG1(DBG_LIB, "invalid key format in SSH key"); reader->destroy(reader); return NULL; } if (chunk_equals(format, chunk_from_str("ssh-rsa"))) { chunk_t n, e; if (!reader->read_data32(reader, &e) || !reader->read_data32(reader, &n)) { DBG1(DBG_LIB, "invalid RSA key in SSH key"); reader->destroy(reader); return NULL; } reader->destroy(reader); return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, BUILD_END); } else if (format.len > strlen(ECDSA_PREFIX) && strneq(format.ptr, ECDSA_PREFIX, strlen(ECDSA_PREFIX))) { chunk_t ec_blob, identifier, q, oid, encoded; sshkey_public_key_t *key; ec_blob = reader->peek(reader); reader->destroy(reader); reader = bio_reader_create(ec_blob); if (!reader->read_data32(reader, &identifier) || !reader->read_data32(reader, &q)) { DBG1(DBG_LIB, "invalid ECDSA key in SSH key"); reader->destroy(reader); return NULL; } oid = parse_ec_identifier(identifier); if (!oid.ptr) { DBG1(DBG_LIB, "invalid ECDSA key identifier in SSH key"); reader->destroy(reader); return NULL; } reader->destroy(reader); /* build key from subjectPublicKeyInfo */ encoded = asn1_wrap(ASN1_SEQUENCE, "mm", asn1_wrap(ASN1_SEQUENCE, "mm", asn1_build_known_oid(OID_EC_PUBLICKEY), oid), asn1_bitstring("c", q)); key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ECDSA, BUILD_BLOB_ASN1_DER, encoded, BUILD_END); chunk_free(&encoded); return key; } DBG1(DBG_LIB, "unsupported SSH key format %.*s", (int)format.len, format.ptr); reader->destroy(reader); return NULL; }