OpenSSL/Print version

From Wikibooks, open books for an open world
Jump to navigation Jump to search


OpenSSL

The current, editable version of this book is available in Wikibooks, the open-content textbooks collection, at
https://en.wikibooks.org/wiki/OpenSSL

Permission is granted to copy, distribute, and/or modify this document under the terms of the Creative Commons Attribution-ShareAlike 3.0 License.

Initialization

Initialization[edit | edit source]

To initialize both libcrypto and libssl:

[first, set up threading callbacks if your program is multithreaded]
SSL_load_error_strings ();
SSL_library_init ();
OpenSSL_add_all_algorithms ();
OPENSSL_config (NULL);

Or to initialize libcrypto only, without libssl:

[first, set up threading callbacks if your program is multithreaded]
ERR_load_crypto_strings ();
OpenSSL_add_all_algorithms ();
OPENSSL_config (NULL);

Note: OPENSSL_config calls ENGINE_load_builtin_engines, so there is no need to call ENGINE_load_builtin_engines if you call OPENSSL_config (indeed, doing so seems to result in a memory leak).

Threading[edit | edit source]

OpenSSL does not have any knowledge of pthreads or Windows threads. Therefore, if your program is multithreaded, you must write callbacks which glue OpenSSL to pthreads or Windows threads (or both, if your program is cross-platform).


Clipboard

To do:
explain how to set up threading callbacks


Cleanup[edit | edit source]

Not really necessary, since resources will be freed on process termination, but you could do:

ERR_free_strings ();
RAND_cleanup ();
EVP_cleanup ();
// this seems to cause double-frees for me: ENGINE_cleanup ();
CONF_modules_free ();
ERR_remove_state (0);


Random numbers

OpenSSL includes a Cryptographically secure pseudorandom number generator. The functions related to the random number generator begin with the prefix RAND_.

OpenSSL automatically seeds the random number generator from /dev/urandom (on UNIX) or CryptGenRandom (on Windows). So, seeding the random number generator is not necessary unless you are on an exotic platform, or wish to add additional entropy.

It's possible to check whether the random number generator has been successfully seeded by calling:

int RAND_status (void);

which returns 1 if the RNG is seeded or 0 if it is not.

The function RAND_poll() can be used to reseed the random number generator using the system entropy source (/dev/urandom or CryptGenRandom). RAND_poll() is called automatically the first time the random number generator is used, so it is not necessary to call it as part of initialization. (Even though many examples of using OpenSSL do so.) However, for a long-running process, it may be desirable to call RAND_poll() occasionally to reseed the random number generator with fresh entropy.


Error handling

Most OpenSSL functions return 1 on success, and something other than 1 on failure. The failure result is often 0, but some functions like ssl_connect() may also return -1 on errors, so it is safest to compare against 1 for success, rather than against 0 for failure.

When an error occurs, more detailed information is stored in the "error queue" (occasionally also referred to as the "error stack" or "error state"), which can contain more than one error code (to record a cascade of errors). The error queue is thread-local (although it is implemented with OpenSSL's home-grown thread local state mechanism, rather than using the OS's mechanism for thread local state).

The simplest thing you can do with the error queue is to print the entire queue. This can be done with ERR_print_errors_fp to print the error queue to a FILE *, or ERR_print_errors to print the error queue to a BIO. Both of these functions empty the error queue after printing it.

Here is an example of how to use a memory BIO to print the error queue to a malloc-allocated string:

char *ossl_err_as_string (void)
{ 
  BIO *bio = BIO_new (BIO_s_mem ());
  ERR_print_errors (bio);
  char *buf = NULL;
  size_t len = BIO_get_mem_data (bio, &buf);
  char *ret = (char *) calloc (1, 1 + len);
  if (ret)
    memcpy (ret, buf, len);
  BIO_free (bio);
  return ret;
}

On the other hand, printing the error stack to standard error is as simple as:

ERR_print_errors_fp (stderr);

TODO: explain more fine-grained ways of extracting individual error codes from the error queue, and interpreting them


Reference counting

  • explain the "add0" and "add1" convention
  • plus, engines have their own reference counting semantics (structural and functional references)


Using BIOs

A BIO is an I/O stream abstraction; essentially OpenSSL's answer to the C library's FILE *. OpenSSL comes with a number of useful BIO types predefined, or you can create your own.

BIOs come in two flavors: source/sink, or filter. BIOs can be chained together. Each chain always has exactly one source/sink, but can have any number (zero or more) of filters.

Reading from a BIO can be done with BIO_read and BIO_gets.

Writing to a BIO can be done with BIO_write, BIO_puts, BIO_printf, and BIO_vprintf.


Pre-defined BIOs

Filter BIOs[edit | edit source]

Source/sink BIOs[edit | edit source]


PEM

PEM stands for Privacy-enhanced Electronic Mail, it's a standard for a public-key cryptography.

Syntax[edit | edit source]

A PEM key must be stored in a file, preferably .pem, beginning and ending by these lines :

-----BEGIN CERTIFICATE REQUEST-----
...
-----END CERTIFICATE REQUEST-----

In Linux, we can identify the PEM certificates with the file command:

file MyCertificate.crt
MyCertificate.crt: PEM certificate request

Conversion[edit | edit source]

To convert a DER certificate to a PEM one:

openssl x509 -inform DER -in /etc/apache2/ssl/MyCertificate.crt -outform PEM -out /etc/apache2/ssl/MyCertificate.pem


EC

The OpenSSL EC library provides an extensive set of functions for performing operations on elliptic curves over finite fields. In general an elliptic curve is one with an equation of the form:

y^2 = x^3 + ax + b

An EC_GROUP structure is used to represent the definition of an elliptic curve. Points on a curve are stored using an EC_POINT structure. An EC_KEY is used to hold a private/public key pair, where a private key is simply a BIGNUM and a public key is a point on a curve (represented by an EC_POINT).

The library contains a number of alternative implementations of the different functions. Each implementation is optimised for different scenarios. No matter which implementation is being used, the interface remains the same. The library handles calling the correct implementation when an interface function is invoked. An implementation is represented by an EC_METHOD structure.

For the creation and destruction of EC_GROUP objects see EC_GROUP_new. For functions for manipulating EC_GROUP objects see EC_GROUP_copy.

Functions for creating, destroying and manipulating EC_POINT objects are explained on the EC_POINT_new page, whilst functions for performing mathematical operations and tests on EC_POINTs are covered in EC_POINT_add.

For working with private and public keys refer to EC_KEY_new. Implementations are covered in EC_GFp_simple_method.

For information on encoding and decoding curve parameters to and from ASN1 see d2i_ECPKParameters.


EC GROUP new

Within the library there are two forms of elliptic curve that are of interest. The first form is those defined over the prime field Fp. The elements of Fp are the integers 0 to p-1, where p is a prime number. This gives us a revised elliptic curve equation as follows:

y^2 mod p = x^3 +ax + b mod p

The second form is those defined over a binary field F2^m where the elements of the field are integers of length at most m bits. For this form the elliptic curve equation is modified to:

y^2 + xy = x^3 + ax^2 + b (where b != 0)

A new curve can be constructed by calling EC_GROUP_new, using the implementation provided by the passed EC_METHOD parameter (see EC_GFp_simple_method). It is then necessary to call either EC_GROUP_set_curve_GFp or EC_GROUP_set_curve_GF2m as appropriate to create a curve defined over Fp or over F2^m respectively.

EC_GROUP_set_curve_GFp sets the curve parameters p, a and b for a curve over Fp stored in group. EC_group_get_curve_GFp obtains the previously set curve parameters.

EC_GROUP_set_curve_GF2m sets the equivalent curve parameters for a curve over F2^m. In this case p = 2^m. EC_group_get_curve_GF2m obtains the previously set curve parameters.

The functions EC_GROUP_new_curve_GFp and EC_GROUP_new_curve_GF2m are shortcuts for calling EC_GROUP_new and the appropriate EC_group_set_curve function. An appropriate default implementation method will be used.

Whilst the library can be used to create any curve using the functions described above, there are also a number of predefined curves that are available. In order to obtain a list of all of the predefined curves, call the function EC_get_builtin_curves. The parameter r should be an array of EC_builtin_curve structures of size nitems. The function will populate the r array with information about the builtin curves. If nitems is less than the total number of curves available, then the first nitems curves will be returned. Otherwise the total number of curves will be provided. The return value is the total number of curves available (whether that number has been populated in r or not). Passing a NULL r, or setting nitems to 0 will do nothing other than return the total number of curves available. The EC_builtin_curve structure is defined as follows:

typedef struct { 
       int nid;
       const char *comment;
       } EC_builtin_curve;

Each EC_builtin_curve item has a unique integer id (nid), and a human readable comment string describing the curve.

In order to construct a builtin curve use the function EC_GROUP_new_by_curve_name and provide the nid of the curve to be constructed.

EC_GROUP_free frees the memory associated with the EC_GROUP.

EC_GROUP_clear_free destroys any sensitive data held within the EC_GROUP and then frees its memory.

Return Values[edit | edit source]

All EC_GROUP_new* functions return a pointer to the newly constructed group, or NULL on error.

EC_get_builtin_curves returns the number of builtin curves that are available.

EC_GROUP_set_curve_GFp, EC_GROUP_get_curve_GFp, EC_GROUP_set_curve_GF2m, EC_GROUP_get_curve_GF2m return 1 on success or 0 on error.


EC GROUP copy

EC_GROUP_copy copies the curve src into dst. Both src and dst must use the same EC_METHOD.

EC_GROUP_dup creates a new EC_GROUP object and copies the content from src to the newly created EC_GROUP object.

EC_GROUP_method_of obtains the EC_METHOD of group.

EC_GROUP_set_generator sets curve parameters that must be agreed by all participants using the curve. These parameters include the generator, the order and the cofactor. The generator is a well defined point on the curve chosen for cryptographic operations. Integers used for point multiplications will be between 0 and n-1 where n is the order. The order multiplied by the cofactor gives the number of points on the curve.

EC_GROUP_get0_generator returns the generator for the identified group.

The functions EC_GROUP_get_order and EC_GROUP_get_cofactor populate the provided order and cofactor parameters with the respective order and cofactors for the group.

The functions EC_GROUP_set_curve_name and EC_GROUP_get_curve_name, set and get the NID for the curve respectively (see EC_GROUP_new). If a curve does not have a NID associated with it, then EC_GROUP_get_curve_name will return 0.

The asn1_flag value on a curve is used to determine whether there is a specific ASN1 OID to describe the curve or not. If the asn1_flag is 1 then this is a named curve with an associated ASN1 OID. If not then asn1_flag is 0. The functions EC_GROUP_get_asn1_flag and EC_GROUP_set_asn1_flag get and set the status of the asn1_flag for the curve. If set then the curve_name must also be set.

The point_conversion_form for a curve controls how EC_POINT data is encoded as ASN1 as defined in X9.62 (ECDSA). point_conversion_form_t is an enum defined as follows:

typedef enum {
       /** the point is encoded as z||x, where the octet z specifies 
        *   which solution of the quadratic equation y is  */
       POINT_CONVERSION_COMPRESSED = 2,
       /** the point is encoded as z||x||y, where z is the octet 0x02  */
       POINT_CONVERSION_UNCOMPRESSED = 4,
       /** the point is encoded as z||x||y, where the octet z specifies
        *  which solution of the quadratic equation y is  */
       POINT_CONVERSION_HYBRID = 6
} point_conversion_form_t;


For POINT_CONVERSION_UNCOMPRESSED the point is encoded as an octet signifying the UNCOMPRESSED form has been used followed by the octets for x, followed by the octets for y.

For any given x co-ordinate for a point on a curve it is possible to derive two possible y values. For POINT_CONVERSION_COMPRESSED the point is encoded as an octet signifying that the COMPRESSED form has been used AND which of the two possible solutions for y has been used, followed by the octets for x.

For POINT_CONVERSION_HYBRID the point is encoded as an octet signifying the HYBRID form has been used AND which of the two possible solutions for y has been used, followed by the octets for x, followed by the octets for y.

The functions EC_GROUP_set_point_conversion_form and EC_GROUP_get_point_conversion_form set and get the point_conversion_form for the curve respectively.

ANSI X9.62 (ECDSA standard) defines a method of generating the curve parameter b from a random number. This provides advantages in that a parameter obtained in this way is highly unlikely to be susceptible to special purpose attacks, or have any trapdoors in it. If the seed is present for a curve then the b parameter was generated in a verifiable fashion using that seed. The OpenSSL EC library does not use this seed value but does enable you to inspect it using EC_GROUP_get0_seed. This returns a pointer to a memory block containing the seed that was used. The length of the memory block can be obtained using EC_GROUP_get_seed_len. A number of the built-in curves within the library provide seed values that can be obtained. It is also possible to set a custom seed using EC_GROUP_set_seed and passing a pointer to a memory block, along with the length of the seed. Again, the EC library will not use this seed value, although it will be preserved in any ASN1 based communications.

EC_GROUP_get_degree gets the degree of the field. For Fp fields this will be the number of bits in p. For F2^m fields this will be the value m.

The function EC_GROUP_check_discriminant calculates the discriminant for the curve and verifies that it is valid. For a curve defined over Fp the discriminant is given by the formula 4*a^3 + 27*b^2 whilst for F2^m curves the discriminant is simply b. In either case for the curve to be valid the discriminant must be non zero.

The function EC_GROUP_check performs a number of checks on a curve to verify that it is valid. Checks performed include verifying that the discriminant is non zero; that a generator has been defined; that the generator is on the curve and has the correct order.

EC_GROUP_cmp compares a and b to determine whether they represent the same curve or not.

The functions EC_GROUP_get_basis_type, EC_GROUP_get_trinomial_basis and EC_GROUP_get_pentanomial_basis should only be called for curves defined over an F2^m field. Addition and multiplication operations within an F2^m field are performed using an irreducible polynomial function f(x). This function is either a trinomial of the form:

f(x) = x^m + x^k + 1 with m > k >= 1

or a pentanomial of the form:

f(x) = x^m + x^k3 + x^k2 + x^k1 + 1 with m > k3 > k2 > k1 >= 1

The function EC_GROUP_get_basis_type returns a NID identifying whether a trinomial or pentanomial is in use for the field. The function EC_GROUP_get_trinomial_basis must only be called where f(x) is of the trinomial form, and returns the value of k. Similarly the function EC_GROUP_get_pentanomial_basis must only be called where f(x) is of the pentanomial form, and returns the values of k1, k2 and k3 respectively.

Return Values[edit | edit source]

The following functions return 1 on success or 0 on error: EC_GROUP_copy, EC_GROUP_set_generator, EC_GROUP_check, EC_GROUP_check_discriminant, EC_GROUP_get_trinomial_basis and EC_GROUP_get_pentanomial_basis.

EC_GROUP_dup returns a pointer to the duplicated curve, or NULL on error.

EC_GROUP_method_of returns the EC_METHOD implementation in use for the given curve or NULL on error.

EC_GROUP_get0_generator returns the generator for the given curve or NULL on error.

EC_GROUP_get_order, EC_GROUP_get_cofactor, EC_GROUP_get_curve_name, EC_GROUP_get_asn1_flag, EC_GROUP_get_point_conversion_form and EC_GROUP_get_degree return the order, cofactor, curve name (NID), ASN1 flag, point_conversion_form and degree for the specified curve respectively. If there is no curve name associated with a curve then EC_GROUP_get_curve_name will return 0.

EC_GROUP_get0_seed returns a pointer to the seed that was used to generate the parameter b, or NULL if the seed is not specified. EC_GROUP_get_seed_len returns the length of the seed or 0 if the seed is not specified.

EC_GROUP_set_seed returns the length of the seed that has been set. If the supplied seed is NULL, or the supplied seed length is 0, the return value will be 1. On error 0 is returned.

EC_GROUP_cmp returns 0 if the curves are equal, 1 if they are not equal, or -1 on error.

EC_GROUP_get_basis_type returns the values NID_X9_62_tpBasis or NID_X9_62_ppBasis (as defined in <openssl/obj_mac.h>) for a trinomial or pentanomial respectively. Alternatively in the event of an error a 0 is returned.


EC POINT new

An EC_POINT represents a point on a curve. A new point is constructed by calling the function EC_POINT_new and providing the group object that the point relates to.

EC_POINT_free frees the memory associated with the EC_POINT.

EC_POINT_clear_free destroys any sensitive data held within the EC_POINT and then frees its memory.

EC_POINT_copy copies the point src into dst. Both src and dst must use the same EC_METHOD.

EC_POINT_dup creates a new EC_POINT object and copies the content from src to the newly created EC_POINT object.

EC_POINT_method_of obtains the EC_METHOD associated with point.

A valid point on a curve is the special point at infinity. A point is set to be at infinity by calling EC_POINT_set_to_infinity.

The affine co-ordinates for a point describe a point in terms of its x and y position. The functions EC_POINT_set_affine_coordinates_GFp and EC_POINT_set_affine_coordinates_GF2m set the x and y co-ordinates for the point p defined over the curve given in group.

As well as the affine co-ordinates, a point can alternatively be described in terms of its Jacobian projective co-ordinates (for Fp curves only). Jacobian projective co-ordinates are expressed as three values x, y and z. Working in this co-ordinate system provides more efficient point multiplication operations. A mapping exists between Jacobian projective co-ordinates and affine co-ordinates. A Jacobian projective co-ordinate (x, y, z) can be written as an affine co-ordinate as (x/(z^2), y/(z^3)). Conversion to Jacobian projective to affine co-ordinates is simple. The co-ordinate (x, y) is mapped to (x, y, 1). To set or get the projective co-ordinates use EC_POINT_set_Jprojective_coordinates_GFp and EC_POINT_get_Jprojective_coordinates_GFp respectively.

Points can also be described in terms of their compressed co-ordinates. For a point (x, y), for any given value for x such that the point is on the curve there will only ever be two possible values for y. Therefore a point can be set using the EC_POINT_set_compressed_coordinates_GFp and EC_POINT_set_compressed_coordinates_GF2m functions where x is the x co-ordinate and y_bit is a value 0 or 1 to identify which of the two possible values for y should be used.

In addition EC_POINTs can be converted to and from various external representations. Supported representations are octet strings, BIGNUMs and hexadecimal. The format of the external representation is described by the point_conversion_form. See EC_GROUP_copy for a description of point_conversion_form. Octet strings are stored in a buffer along with an associated buffer length. A point held in a BIGNUM is calculated by converting the point to an octet string and then converting that octet string into a BIGNUM integer. Points in hexadecimal format are stored in a NULL terminated character string where each character is one of the printable values 0-9 or A-F (or a-f).

Return Values[edit | edit source]

EC_POINT_new and EC_POINT_dup return the newly allocated EC_POINT or NULL on error.

The following functions return 1 on success or 0 on error: EC_POINT_copy, EC_POINT_set_to_infinity, EC_POINT_set_Jprojective_coordinates_GFp, EC_POINT_get_Jprojective_coordinates_GFp, EC_POINT_set_affine_coordinates_GFp, EC_POINT_get_affine_coordinates_GFp, EC_POINT_set_compressed_coordinates_GFp, EC_POINT_set_affine_coordinates_GF2m, EC_POINT_get_affine_coordinates_GF2m, EC_POINT_set_compressed_coordinates_GF2m and EC_POINT_oct2point.

EC_POINT_method_of returns the EC_METHOD associated with the supplied EC_POINT.

EC_POINT_point2oct returns the length of the required buffer, or 0 on error.

EC_POINT_point2bn returns the pointer to the BIGNUM supplied, or NULL on error.

EC_POINT_bn2point returns the pointer to the EC_POINT supplied, or NULL on error.

EC_POINT_point2hex returns a pointer to the hex string, or NULL on error.

EC_POINT_hex2point returns the pointer to the EC_POINT supplied, or NULL on error.

The functions EC_POINT_point2oct, EC_POINT_oct2point, EC_POINT_point2bn, EC_POINT_bn2point, EC_POINT_point2hex and EC_POINT_hex2point convert from and to EC_POINTs for the formats: octet string, BIGNUM and hexadecimal respectively.

The function EC_POINT_point2oct must be supplied with a buffer long enough to store the octet string. The return value provides the number of octets stored. Calling the function with a NULL buffer will not perform the conversion but will still return the required buffer length.

The function EC_POINT_point2hex will allocate sufficient memory to store the hexadecimal string. It is the caller's responsibility to free this memory with a subsequent call to OPENSSL_free().


EC POINT add

EC_POINT_add adds the two points a and b and places the result in r. Similarly EC_POINT_dbl doubles the point a and places the result in r. In both cases it is valid for r to be one of a or b.

EC_POINT_invert calculates the inverse of the supplied point a. The result is placed back in a.

The function EC_POINT_is_at_infinity tests whether the supplied point is at infinity or not.

EC_POINT_is_on_curve tests whether the supplied point is on the curve or not.

EC_POINT_cmp compares the two supplied points and tests whether or not they are equal.

The functions EC_POINT_make_affine and EC_POINTs_make_affine force the internal representation of the EC_POINT(s) into the affine co-ordinate system. In the case of EC_POINTs_make_affine the value num provides the number of points in the array points to be forced.

EC_POINT_mul calculates the value generator * n + q * m and stores the result in r. The value n may be NULL in which case the result is just q * m.

EC_POINTs_mul calculates the value generator * n + q[0] * m[0] + ... + q[num-1] * m[num-1]. As for EC_POINT_mul the value n may be NULL.

The function EC_GROUP_precompute_mult stores multiples of the generator for faster point multiplication, whilst EC_GROUP_have_precompute_mult tests whether precomputation has already been done. See EC_GROUP_copy for information about the generator.

Return Values[edit | edit source]

The following functions return 1 on success or 0 on error: EC_POINT_add, EC_POINT_dbl, EC_POINT_invert, EC_POINT_make_affine, EC_POINTs_make_affine, EC_POINTs_make_affine, EC_POINT_mul, EC_POINTs_mul and EC_GROUP_precompute_mult.

EC_POINT_is_at_infinity returns 1 if the point is at infinity, or 0 otherwise.

EC_POINT_is_on_curve returns 1 if the point is on the curve, 0 if not, or -1 on error.

EC_POINT_cmp returns 1 if the points are not equal, 0 if they are, or -1 on error.

EC_GROUP_have_precompute_mult return 1 if a precomputation has been done, or 0 if not.


EC KEY new

An EC_KEY represents a public key and (optionaly) an associated private key. A new EC_KEY (with no associated curve) can be constructed by calling EC_KEY_new. The reference count for the newly created EC_KEY is initially set to 1. A curve can be associated with the EC_KEY by calling EC_KEY_set_group.

Alternatively a new EC_KEY can be constructed by calling EC_KEY_new_by_curve_name and supplying the nid of the associated curve. Refer to EC_GROUP_new for a description of curve names. This function simply wraps calls to EC_KEY_new and EC_GROUP_new_by_curve_name.

Calling EC_KEY_free decrements the reference count for the EC_KEY object, and if it has dropped to zero then frees the memory associated with it.

EC_KEY_copy copies the contents of the EC_KEY in src into dest.

EC_KEY_dup creates a new EC_KEY object and copies ec_key into it.

EC_KEY_up_ref increments the reference count associated with the EC_KEY object.

EC_KEY_generate_key generates a new public and private key for the supplied eckey object. eckey must have an EC_GROUP object associated with it before calling this function. The private key is a random integer (0 < priv_key < order, where order is the order of the EC_GROUP object). The public key is an EC_POINT on the curve calculated by multiplying the generator for the curve by the private key.

EC_KEY_check_key performs various sanity checks on the EC_KEY object to confirm that it is valid.

EC_KEY_set_public_key_affine_coordinates sets the public key for key based on its affine co-ordinates, i.e. it constructs an EC_POINT object based on the supplied x and y values and sets the public key to be this EC_POINT. It will also performs certain sanity checks on the key to confirm that it is valid.

The functions EC_KEY_get0_group, EC_KEY_set_group, EC_KEY_get0_private_key, EC_KEY_set_private_key, EC_KEY_get0_public_key, and EC_KEY_set_public_key get and set the EC_GROUP object, the private key and the EC_POINT public key for the key respectively.

The functions EC_KEY_get_enc_flags and EC_KEY_set_enc_flags get and set the value of the encoding flags for the key. There are two encoding flags currently defined - EC_PKEY_NO_PARAMETERS and EC_PKEY_NO_PUBKEY. These flags define the behaviour of how the key is converted into ASN1 in a call to i2d_ECPrivateKey. If EC_PKEY_NO_PARAMETERS is set then the public parameters for the curve are not encoded along with the private key. If EC_PKEY_NO_PUBKEY is set then the public key is not encoded along with the private key.

The functions EC_KEY_get_conv_form and EC_KEY_set_conv_form get and set the point_conversion_form for the key. For a description of point_conversion_forms please refer to EC_POINT_new.

EC_KEY_insert_key_method_data and EC_KEY_get_key_method_data enable the caller to associate arbitary additional data specific to the elliptic curve scheme being used with the EC_KEY object. This data is treated as a "black box" by the ec library. The data to be stored by EC_KEY_insert_key_method_data is provided in the data parameter, which must have have associated functions for duplicating, freeing and "clear_freeing" the data item. If a subsequent EC_KEY_get_key_method_data call is issued, the functions for duplicating, freeing and "clear_freeing" the data item must be provided again, and they must be the same as they were when the data item was inserted.

EC_KEY_set_flags sets the flags in the flags parameter on the EC_KEY object. Any flags that are already set are left set. The currently defined standard flags are EC_FLAG_NON_FIPS_ALLOW and EC_FLAG_FIPS_CHECKED. In addition there is the flag EC_FLAG_COFACTOR_ECDH which is specific to ECDH and is defined in ecdh.h. EC_KEY_get_flags returns the current flags that are set for this EC_KEY. EC_KEY_clear_flags clears the flags indicated by the flags parameter. All other flags are left in their existing state.

EC_KEY_set_asn1_flag sets the asn1_flag on the underlying EC_GROUP object (if set). Refer to EC_GROUP_copy for further information on the asn1_flag.

EC_KEY_precompute_mult stores multiples of the underlying EC_GROUP generator for faster point multiplication. See also EC_POINT_add.

Return Values[edit | edit source]

EC_KEY_new, EC_KEY_new_by_curve_name and EC_KEY_dup return a pointer to the newly created EC_KEY object, or NULL on error.

EC_KEY_get_flags returns the flags associated with the EC_KEY object as an integer.

EC_KEY_copy returns a pointer to the destination key, or NULL on error.

EC_KEY_up_ref, EC_KEY_set_group, EC_KEY_set_private_key, EC_KEY_set_public_key, EC_KEY_precompute_mult, EC_KEY_generate_key, EC_KEY_check_key and EC_KEY_set_public_key_affine_coordinates return 1 on success or 0 on error.

EC_KEY_get0_group returns the EC_GROUP associated with the EC_KEY.

EC_KEY_get0_private_key returns the private key associated with the EC_KEY.

EC_KEY_get_enc_flags returns the value of the current encoding flags for the EC_KEY.

EC_KEY_get_conv_form return the point_conversion_form for the EC_KEY.


EC GFp simple method

The Elliptic Curve library provides a number of different implementations through a single common interface. When constructing a curve using EC_GROUP_new (see EC_GROUP_new) an implementation method must be provided. The functions described here all return a const pointer to an EC_METHOD structure that can be passed to EC_GROUP_NEW. It is important that the correct implementation type for the form of curve selected is used.

For F2^m curves there is only one implementation choice, i.e. EC_GF2_simple_method.

For Fp curves the lowest common denominator implementation is the EC_GFp_simple_method implementation. All other implementations are based on this one. EC_GFp_mont_method builds on EC_GFp_simple_method but adds the use of montgomery multiplication (refer to Bignum). EC_GFp_nist_method offers an implementation optimised for use with NIST recommended curves (NIST curves are available through EC_GROUP_new_by_curve_name as described in EC_GROUP_new).

The functions EC_GFp_nistp224_method, EC_GFp_nistp256_method and EC_GFp_nistp521_method offer 64 bit optimised implementations for the NIST P224, P256 and P521 curves respectively. Note, however, that these implementations are not available on all platforms.

EC_METHOD_get_field_type identifies what type of field the EC_METHOD structure supports, which will be either F2^m or Fp. If the field type is Fp then the value NID_X9_62_prime_field is returned. If the field type is F2^m then the value NID_X9_62_characteristic_two_field is returned. These values are defined in the obj_mac.h header file.

Return Values[edit | edit source]

All EC_GFp* functions and EC_GF2m_simple_method always return a const pointer to an EC_METHOD structure.

EC_METHOD_get_field_type returns an integer that identifies the type of field the EC_METHOD structure supports.


d2i ECPKParameters

The ECPKParameters encode and decode routines encode and parse the public parameters for an EC_GROUP structure, which represents a curve.

d2i_ECPKParameters() attempts to decode len bytes at *in. If successful a pointer to the EC_GROUP structure is returned. If an error occurred then NULL is returned. If px is not NULL then the returned structure is written to *px. If *px is not NULL then it is assumed that *px contains a valid EC_GROUP structure and an attempt is made to reuse it. If the call is successful *in is incremented to the byte following the parsed data.

i2d_ECPKParameters() encodes the structure pointed to by x into DER format. If out is not NULL is writes the DER encoded data to the buffer at *out, and increments it to point after the data just written. If the return value is negative an error occurred, otherwise it returns the length of the encoded data.

If *out is NULL memory will be allocated for a buffer and the encoded data written to it. In this case *out is not incremented and it points to the start of the data just written.

d2i_ECPKParameters_bio() is similar to d2i_ECPKParameters() except it attempts to parse data from BIO bp.

d2i_ECPKParameters_fp() is similar to d2i_ECPKParameters() except it attempts to parse data from FILE pointer fp.

i2d_ECPKParameters_bio() is similar to i2d_ECPKParameters() except it writes the encoding of the structure x to BIO bp and it returns 1 for success and 0 for failure.

i2d_ECPKParameters_fp() is similar to i2d_ECPKParameters() except it writes the encoding of the structure x to BIO bp and it returns 1 for success and 0 for failure.

These functions are very similar to the X509 functions described on the OpenSSL d2i_X509 manual page, where further notes and examples are available.

The ECPKParameters_print and ECPKParameters_print_fp functions print a human-readable output of the public parameters of the EC_GROUP to bp or fp. The output lines are indented by off spaces.

Return Values[edit | edit source]

d2i_ECPKParameters(), d2i_ECPKParameters_bio() and d2i_ECPKParameters_fp() return a valid EC_GROUP structure or NULL if an error occurs.

i2d_ECPKParameters() returns the number of bytes successfully encoded or a negative value if an error occurs.

i2d_ECPKParameters_bio(), i2d_ECPKParameters_fp(), ECPKParameters_print and ECPKParameters_print_fp return 1 for success and 0 if an error occurs.


Engine architecture

[1]

To print a list of engines:

  ENGINE *e;
  int nengines = 0;

  ENGINE_load_builtin_engines ();

  for (e = ENGINE_get_first ()  ;  e != NULL  ;  e = ENGINE_get_next (e))
    {
      printf ("engine: %s\n", ENGINE_get_name (e));
      nengines++;
    }

  printf ("%d engines\n", nengines);


Windows

explain Applink, and any other Windows peculiarities


Configuration

Document stuff like OPENSSL_config and CONF_load_modules_file.


Diffie-Hellman parameters

To use Perfect Forward Secrecy cipher suites, you must set up Diffie-Hellman parameters (on the server side), or the PFS cipher suites will be silently ignored.

Diffie-Hellman[edit | edit source]

SSL_CTX_set_tmp_dh is used to set the Diffie-Hellman parameters for a context. One of the easiest ways to get Diffie-Hellman parameters to use with this function is to generate random Diffie-Hellman parameters with the dhparam command-line program with the -C option, and embed the resulting code fragment in your program. For example, openssl dhparam -C 2236 might result in:

#ifndef HEADER_DH_H
#include <openssl/dh.h>
#endif
DH *get_dh2236()
	{
	static unsigned char dh2236_p[]={
		0x0F,0x52,0xE5,0x24,0xF5,0xFA,0x9D,0xDC,0xC6,0xAB,0xE6,0x04,
		0xE4,0x20,0x89,0x8A,0xB4,0xBF,0x27,0xB5,0x4A,0x95,0x57,0xA1,
		0x06,0xE7,0x30,0x73,0x83,0x5E,0xC9,0x23,0x11,0xED,0x42,0x45,
		0xAC,0x49,0xD3,0xE3,0xF3,0x34,0x73,0xC5,0x7D,0x00,0x3C,0x86,
		0x63,0x74,0xE0,0x75,0x97,0x84,0x1D,0x0B,0x11,0xDA,0x04,0xD0,
		0xFE,0x4F,0xB0,0x37,0xDF,0x57,0x22,0x2E,0x96,0x42,0xE0,0x7C,
		0xD7,0x5E,0x46,0x29,0xAF,0xB1,0xF4,0x81,0xAF,0xFC,0x9A,0xEF,
		0xFA,0x89,0x9E,0x0A,0xFB,0x16,0xE3,0x8F,0x01,0xA2,0xC8,0xDD,
		0xB4,0x47,0x12,0xF8,0x29,0x09,0x13,0x6E,0x9D,0xA8,0xF9,0x5D,
		0x08,0x00,0x3A,0x8C,0xA7,0xFF,0x6C,0xCF,0xE3,0x7C,0x3B,0x6B,
		0xB4,0x26,0xCC,0xDA,0x89,0x93,0x01,0x73,0xA8,0x55,0x3E,0x5B,
		0x77,0x25,0x8F,0x27,0xA3,0xF1,0xBF,0x7A,0x73,0x1F,0x85,0x96,
		0x0C,0x45,0x14,0xC1,0x06,0xB7,0x1C,0x75,0xAA,0x10,0xBC,0x86,
		0x98,0x75,0x44,0x70,0xD1,0x0F,0x20,0xF4,0xAC,0x4C,0xB3,0x88,
		0x16,0x1C,0x7E,0xA3,0x27,0xE4,0xAD,0xE1,0xA1,0x85,0x4F,0x1A,
		0x22,0x0D,0x05,0x42,0x73,0x69,0x45,0xC9,0x2F,0xF7,0xC2,0x48,
		0xE3,0xCE,0x9D,0x74,0x58,0x53,0xE7,0xA7,0x82,0x18,0xD9,0x3D,
		0xAF,0xAB,0x40,0x9F,0xAA,0x4C,0x78,0x0A,0xC3,0x24,0x2D,0xDB,
		0x12,0xA9,0x54,0xE5,0x47,0x87,0xAC,0x52,0xFE,0xE8,0x3D,0x0B,
		0x56,0xED,0x9C,0x9F,0xFF,0x39,0xE5,0xE5,0xBF,0x62,0x32,0x42,
		0x08,0xAE,0x6A,0xED,0x88,0x0E,0xB3,0x1A,0x4C,0xD3,0x08,0xE4,
		0xC4,0xAA,0x2C,0xCC,0xB1,0x37,0xA5,0xC1,0xA9,0x64,0x7E,0xEB,
		0xF9,0xD3,0xF5,0x15,0x28,0xFE,0x2E,0xE2,0x7F,0xFE,0xD9,0xB9,
		0x38,0x42,0x57,0x03,
		};
	static unsigned char dh2236_g[]={
		0x02,
		};
	DH *dh;

	if ((dh=DH_new()) == NULL) return(NULL);
	dh->p=BN_bin2bn(dh2236_p,sizeof(dh2236_p),NULL);
	dh->g=BN_bin2bn(dh2236_g,sizeof(dh2236_g),NULL);
	if ((dh->p == NULL) || (dh->g == NULL))
		{ DH_free(dh); return(NULL); }
	return(dh);
	}

which can then be used like this:

DH *dh = get_dh2236 ();
if (1 != SSL_CTX_set_tmp_dh (ctx, dh))
  error ();
DH_free (dh);

Be sure to choose a bit length appropriate to the security level you want to achieve, although keep in mind that Diffie-Hellman parameters longer than 2236 bits may be incompatible with older versions of NSS.

Elliptic curve Diffie-Hellman[edit | edit source]

For elliptic curve Diffie-Hellman, you can do something like this:

EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);
if (! ecdh)
  error ();
if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh))
  error ();
EC_KEY_free (ecdh);

Or, in OpenSSL 1.0.2 (not yet released, as of Feb 2013) and higher, you should be able to do:

SSL_CTX_set_ecdh_auto (ctx, 1)


Verify callbacks

/* This is helpful for debugging the unhelpful error
 * "unable to get local issuer certificate", which could mean
 * almost anything.  But, unfortunately, this is a little too
 * verbose for normal use. */
X509_VERIFY_PARAM *vp = X509_VERIFY_PARAM_new ();
if (1 != X509_VERIFY_PARAM_set_flags (vp, X509_V_FLAG_CB_ISSUER_CHECK))
  error ();
if (1 != SSL_CTX_set1_param (context, vp))
  error ();
X509_VERIFY_PARAM_free (vp);


Hostname validation

  • include a link to [2] and explain how to use it and why it's important
  • mention that future (not yet released) versions of OpenSSL will have this functionality built in


Notes for contributors

Ideally, the chapters in this wikibook should have a narrative structure. Not quite a tutorial or HOWTO, but not an API reference, either. The book should explain the API, but with a focus on introducing the big ideas, explaining when and why you would want to use a particular function, and show how to use the various API functions together to accomplish real-world tasks.

Although this is the eventual goal, I certainly don't want to discourage anyone from contributing content, especially at this early stage. Once we have content, we can restructure and evolve it to have more of the narrative flow of a book.

The front page of the book is modeled after the Haskell wikibook, although without using templates. (Since the templates make it more complicated, and WikiBooks won't let me create templates, anyway.) All of the pages of the book should be listed in the table of contents. If the number of pages becomes unwieldy for the current structure of the table of contents, we can restructure the table of contents.