diff options
author | lloyd <[email protected]> | 2010-03-04 02:22:02 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2010-03-04 02:22:02 +0000 |
commit | 1b0f06037e00d426f37c9180f02f1ec2157644bd (patch) | |
tree | 8e51945448aac864b41d4e5564db12411a168051 /src/pubkey/x509_key.cpp | |
parent | af204bf9828c20e485f9c9bde98160bd3506e81a (diff) |
The code in pk_codecs was actually entirely tied to the code in
pubkey; you literally could not compile any pubkey code without it.
Move it up to the pubkey dir, it wasn't at all useful to have it
in its own dir.
Diffstat (limited to 'src/pubkey/x509_key.cpp')
-rw-r--r-- | src/pubkey/x509_key.cpp | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/src/pubkey/x509_key.cpp b/src/pubkey/x509_key.cpp new file mode 100644 index 000000000..fdcfccf87 --- /dev/null +++ b/src/pubkey/x509_key.cpp @@ -0,0 +1,172 @@ +/* +* X.509 Public Key +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/x509_key.h> +#include <botan/filters.h> +#include <botan/asn1_obj.h> +#include <botan/der_enc.h> +#include <botan/ber_dec.h> +#include <botan/oids.h> +#include <botan/pem.h> +#include <botan/internal/pk_algs.h> +#include <memory> + +namespace Botan { + +namespace X509 { + +/* +* DER or PEM encode a X.509 public key +*/ +void encode(const Public_Key& key, Pipe& pipe, X509_Encoding encoding) + { + MemoryVector<byte> der = + DER_Encoder() + .start_cons(SEQUENCE) + .encode(key.algorithm_identifier()) + .encode(key.x509_subject_public_key(), BIT_STRING) + .end_cons() + .get_contents(); + + if(encoding == PEM) + pipe.write(PEM_Code::encode(der, "PUBLIC KEY")); + else + pipe.write(der); + } + +/* +* PEM encode a X.509 public key +*/ +std::string PEM_encode(const Public_Key& key) + { + Pipe pem; + pem.start_msg(); + encode(key, pem, PEM); + pem.end_msg(); + return pem.read_all_as_string(); + } + +/* +* Extract a public key and return it +*/ +Public_Key* load_key(DataSource& source) + { + try { + AlgorithmIdentifier alg_id; + MemoryVector<byte> key_bits; + + if(ASN1::maybe_BER(source) && !PEM_Code::matches(source)) + { + BER_Decoder(source) + .start_cons(SEQUENCE) + .decode(alg_id) + .decode(key_bits, BIT_STRING) + .verify_end() + .end_cons(); + } + else + { + DataSource_Memory ber( + PEM_Code::decode_check_label(source, "PUBLIC KEY") + ); + + BER_Decoder(ber) + .start_cons(SEQUENCE) + .decode(alg_id) + .decode(key_bits, BIT_STRING) + .verify_end() + .end_cons(); + } + + if(key_bits.empty()) + throw Decoding_Error("X.509 public key decoding failed"); + + const std::string alg_name = OIDS::lookup(alg_id.oid); + if(alg_name == "") + throw Decoding_Error("Unknown algorithm OID: " + + alg_id.oid.as_string()); + + std::auto_ptr<Public_Key> key_obj(get_public_key(alg_name)); + if(!key_obj.get()) + throw Decoding_Error("Unknown PK algorithm/OID: " + alg_name + ", " + + alg_id.oid.as_string()); + + std::auto_ptr<X509_Decoder> decoder(key_obj->x509_decoder()); + + if(!decoder.get()) + throw Decoding_Error("Key does not support X.509 decoding"); + + decoder->alg_id(alg_id); + decoder->key_bits(key_bits); + + return key_obj.release(); + } + catch(Decoding_Error) + { + throw Decoding_Error("X.509 public key decoding failed"); + } + } + +/* +* Extract a public key and return it +*/ +Public_Key* load_key(const std::string& fsname) + { + DataSource_Stream source(fsname, true); + return X509::load_key(source); + } + +/* +* Extract a public key and return it +*/ +Public_Key* load_key(const MemoryRegion<byte>& mem) + { + DataSource_Memory source(mem); + return X509::load_key(source); + } + +/* +* Make a copy of this public key +*/ +Public_Key* copy_key(const Public_Key& key) + { + Pipe bits; + bits.start_msg(); + X509::encode(key, bits, RAW_BER); + bits.end_msg(); + DataSource_Memory source(bits.read_all()); + return X509::load_key(source); + } + +/* +* Find the allowable key constraints +*/ +Key_Constraints find_constraints(const Public_Key& pub_key, + Key_Constraints limits) + { + const Public_Key* key = &pub_key; + u32bit constraints = 0; + + if(dynamic_cast<const PK_Encrypting_Key*>(key)) + constraints |= KEY_ENCIPHERMENT | DATA_ENCIPHERMENT; + + if(dynamic_cast<const PK_Key_Agreement_Key*>(key)) + constraints |= KEY_AGREEMENT; + + if(dynamic_cast<const PK_Verifying_wo_MR_Key*>(key) || + dynamic_cast<const PK_Verifying_with_MR_Key*>(key)) + constraints |= DIGITAL_SIGNATURE | NON_REPUDIATION; + + if(limits) + constraints &= limits; + + return Key_Constraints(constraints); + } + +} + +} |