diff options
Diffstat (limited to 'doc/porting.txt')
-rw-r--r-- | doc/porting.txt | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/doc/porting.txt b/doc/porting.txt new file mode 100644 index 000000000..48c095837 --- /dev/null +++ b/doc/porting.txt @@ -0,0 +1,144 @@ +* Botan Porting Guide, 1.2.x -> 1.4.x + +This is a guide for how to port your code from 1.2.x to 1.4.x. For the most +part, they are compatible, but there are a few cases that might cause +problems. The externally visible changes are much smaller than 1.0->1.2 changes +were. If you run into something that used to work that doesn't now and isn't +mentioned here, let me know so I can either fix it, or document it here. + +If you can provide a solid reason for 1.4.x to supply backwards-compatible +behavior with something that's mentioned here, I'll consider it, but no +promises. + +* Memory Containers + +The memory containers (SecureBuffer, SecureVector) have been changed to +subclass another object, MemoryRegion (a third subclass, MemoryVector, is just +like SecureVector, except it never locks memory - though it will clear it when +freeing). On it's own, this shouldn't cause any problems, but there are some +cases to be aware of. + +The ptr() function was renamed begin() to match the STL. This is probably the +change most likely to cause problems. + +Various other functions (such as compare) were removed or renamed. The ones +that were removed can be replaced with STL algorithms (for example, compare -> +lexicographical_compare) and the renamed ones were typically renamed to match +the STL. + +SecureBuffer can now be resized, so the second template parameter shouldn't be +considered to be the same as the actual size; it is instead the *initial* size +of the buffer. You can get the current size by calling the size() member +function. While it's possible to modify the size of a SecureBuffer now, don't +do it: it's really confusing, and you should just use a SecureVector instead. + +Second (optional, but a good idea): convert any functions taking a "const +SecureVector<T>&" to "const MemoryRegion<T>&"; this will let them work with +arbitrary memory types; in particular, it will work with a MemoryVector, which +doesn't lock. In fact, the compiler will convert it for you, but this will slow +things down quite a bit (since copying it requires an allocation and a memcpy), +so it's a good idea to do the change. + +* OctetString / SymmetricKey / InitializationVector + +This probably wins the 'most likely to cause compile errors' award. There are +two changes: + +1) copy() was renamed bits_of() + +2) The implicit conversion to byte* was removed. If you were passing it to + another library function as a byte*/u32bit pair, there is probably a version + taking the object directly; use that instead. + + If you were using it for something else, do the following: 1) call bits_of() + and use the returned SecureVector<byte> to get the byte* value, and 2) email + me so I can figure out if what you're doing it worth supporting in the + library (obviously strike this last part if what you're doing is so totally + one-off that nobody would ever need it elsewhere). + +* BigInt::zero() / BigInt::one() + +They were removed. Just use integer constants (0/1) instead; the performance +gain was extremely questionable, and there was lots of special glue to make +sure they worked correctly. + +* ASN.1 decoding + +If something took an X509_Encoding flag before, it probably doesn't +anymore. Some magical heuristics (BER::maybe_BER and PEM_Code::matches) have +been added which can successfully tell if something is PEM or BER/DER encoded +by looking at the data. The heuristics are not perfect (that's why I'm calling +them heuristics), but they work pretty well, and for the most part you would +have to go quite out of your way to fool them (you will be rewarded for your +hard work with an exception, when the decoding fails). + +The places that took it for encoding still do, as the library has no way to +guess which format you want it in. + +* General PK + +PK_Key::check_params() was renamed check_key() to better reflect what +operations are performed. + +* X.509 + +The first two arguments of X509_CA::update_crl (the list of new entries and the +CRL) have been swapped. Now the CRL is the first argument, and the list of +entires is the second. This just seemed a lot more natural. + +CRL_Usage was moved from being a global enumeration to a member of X509_Store, +which makes more sense as that is the only class that uses it. Just replace +CRL_Usage with X509_Store::CRL_Usage, and similarly for any elements of +CRL_Usage (ie, instead of TLS_SERVER, use X509_Store::TLS_SERVER). + +* PKCS #8 + +The PKCS #8 key loading interface has changed significantly in 1.4.0. First, +the versions taking memory objects have been completely removed. While it is, +in fact, quite useful to do this, it's not so useful that it's worth supporting +it in the library (IMO). Just create a DataSource_Memory and pass that to +load_key instead. In fact, here's the code: + +PKCS8_PrivateKey* load_key(const SecureVector<byte>& buffer, + const std::string& pass) + { + DataSource_Memory source(buffer); + return PKCS8::load_key(source, pass); + } + +See, that was easy. :) + +Second, instead of passing a std::string, representing the passphrase, you pass +a User_Interface& object, which a) will not be used if the key isn't encrypted, +and b) will be called as many times as needed until the correct passphrase it +entered (or until the number of tries exceeds the config option +"base/pkcs8_tries", which defaults to 3 (or until the ui object returns +CANCEL_ACTION)). + +The base User_Interface class is pretty brain-dead. The constructor takes an +(optional) passphrase, which it spits back out the first time it's called. The +second time it gets called, it will return CANCEL_ACTION. This behavior is for +compatibility with the old std::string interface (the functions still exist as +forwarding functions, which just create the base UI object and pass it to the +real decoding functions). + +Updating your code to use the new PKCS #8 functions could make things much +nicer in your interface (for example, popping up a dialog box that asks for the +passphrase, but only if the key really is encrypted). There is a GTK+ example +that shows how to do this, check the web page. + +* Public/Private Keys + +This is a pretty big change. Almost all of the PK objects used to have a +constructor taking a DataSource&, from which it would read the key. However, +this was a poor design, because if you guess incorrectly as to what kind of key +was in use, bad stuff would happen. So basically it was impossible to use +safely. In addition, it was rather complex to support. + +Use {X509,PKCS8}::load_key and dynamic_cast<> instead. It's a bit more code, +but it's worth it for the flexibility and better error handling. If you really +want something like the constructors, you can look at the try_load functions in +1.2.x's pkcs8.cpp and x509_key.cpp to see how they did it (you won't get the +same exact effect, since you can't add a constructor, but you can do something +that looks fairly similar). + |