blob: 852896ea0ca0bb3ee5f04d3236223ef471ebfb4a [file] [log] [blame]
Laurens Van Houtven7d2c74e2014-06-23 13:49:58 +02001C bindings
2==========
3
4C bindings are bindings to C libraries, using cffi_ whenever possible.
5
Laurens Van Houtven4e006142014-06-23 14:05:10 +02006.. _cffi: http://cffi.readthedocs.org
Laurens Van Houtven7d2c74e2014-06-23 13:49:58 +02007
8Bindings live in :py:mod:`cryptography.hazmat.bindings`.
Laurens Van Houtvenefa5cfb2014-06-23 13:51:35 +02009
Laurens Van Houtven220a98d2014-06-23 14:08:27 +020010Style guide
11-----------
12
13Don't name parameters:
14
15.. code-block:: c
16
17 /* Good */
18 long f(long);
19 /* Bad */
20 long f(long x);
21
22...unless they're inside a struct:
23
24.. code-block:: c
25
26 struct my_struct {
27 char *name;
28 int number;
29 ...;
30 };
31
32Include ``void`` if the function takes no arguments:
33
34.. code-block:: c
35
36 /* Good */
37 long f(void);
38 /* Bad */
39 long f();
40
41Wrap lines at 80 characters like so:
42
43.. code-block:: c
44
45 /* Pretend this went to 80 characters */
46 long f(long, long,
47 int *)
48
49Include a space after commas between parameters:
50
51.. code-block:: c
52
53 /* Good */
54 long f(int, char *)
55 /* Bad */
56 long f(int,char *)
57
58Use C-style ``/* */`` comments instead of C++-style ``//``:
59
60.. code-block:: c
61
62 // Bad
63 /* Good */
64
65Values set by ``#define`` should be assigned the appropriate type. If you see
66this:
67
68.. code-block:: c
69
70 #define SOME_INTEGER_LITERAL 0x0;
71 #define SOME_UNSIGNED_INTEGER_LITERAL 0x0001U;
72 #define SOME_STRING_LITERAL "hello";
73
74...it should be added to the bindings like so:
75
76.. code-block:: c
77
78 static const int SOME_INTEGER_LITERAL;
79 static const unsigned int SOME_UNSIGNED_INTEGER_LITERAL;
80 static const char *const SOME_STRING_LITERAL;
81
Laurens Van Houtvenefa5cfb2014-06-23 13:51:35 +020082Adding constant, types, functions...
83------------------------------------
84
85You can create bindings for any name that exists in some version of
86the library you're binding against. However, the project also has to
Laurens Van Houtven1159af82014-06-23 16:23:24 +020087keep supporting older versions of the library. In order to achieve
Laurens Van Houtvenefa5cfb2014-06-23 13:51:35 +020088this, binding modules have ``CUSTOMIZATIONS`` and
89``CONDITIONAL_NAMES`` constants.
90
91Let's say you want to enable quantum transmogrification. The upstream
92library implements this as the following API::
93
94 static const int QM_TRANSMOGRIFICATION_ALIGNMENT_LEFT;
95 static const int QM_TRANSMOGRIFICATION_ALIGNMENT_RIGHT;
96 typedef ... QM_TRANSMOGRIFICATION_CTX;
97 int QM_transmogrify(QM_TRANSMOGRIFICATION_CTX *, int);
98
99To start, create a new constant that defines if the *actual* library
100has the feature you want, and add it to ``TYPES``::
101
102 static const long Cryptography_HAS_QUANTUM_TRANSMOGRIFICATION;
103
104This should start with ``Cryptography_``, since we're adding it in
105this library. This prevents namespace collisions.
106
107Then, define the actual features (constants, types, functions...) you
108want to expose. If it's a constant, just add it to ``TYPES``::
109
110 static const int QM_TRANSMOGRIFICATION_ALIGNMENT_LEFT;
111 static const int QM_TRANSMOGRIFICATION_ALIGNMENT_RIGHT;
112
113If it's a struct, add it to ``TYPES`` as well. The following is an
114opaque struct::
115
116 typedef ... QM_TRANSMOGRIFICATION_CTX;
117
118... but you can also make some or all items in the struct accessible::
119
120 typedef struct {
121 /* Fundamental constant k for your particular universe */
122 BIGNUM *k;
123 ...;
124 } QM_TRANSMOGRIFICATION_CTX;
125
126Confusingly, functions that aren't always available on all supported
127versions of the library, should be defined in ``MACROS`` and *not* in
128``FUNCTIONS``. Fortunately, you just have to copy the signature::
129
130 int QM_transmogrify(QM_TRANSMOGRIFICATION_CTX *, int);
131
132Then, we define the ``CUSTOMIZATIONS`` entry. To do that, we have to
133come up with a C preprocessor expression that decides whether or not a
134feature exists in the library. For example::
135
136 #ifdef QM_transmogrify
137
138Then, we set the flag that signifies the feature exists::
139
140 static const long Cryptography_HAS_QUANTUM_TRANSMOGRIFICATION = 1;
141
142Otherwise, we set that flag to 0::
143
144 #else
145 static const long Cryptography_HAS_QUANTUM_TRANSMOGRIFICATION = 0;
146
147Then, in that ``#else`` block, we define a number of fallbacks. For an
148integer constant, just define it as 0::
149
150 static const int QM_TRANSMOGRIFICATION_ALIGNMENT_LEFT = 0;
151 static const int QM_TRANSMOGRIFICATION_ALIGNMENT_RIGHT = 0;
152
153For a function, it's a bit trickier. You have to define a function
154pointer of the appropriate type to be NULL::
155
156 int (*QM_transmogrify)(QM_TRANSMOGRIFICATION_CTX *, int) = NULL;
157
Laurens Van Houtven1dc0b142014-06-23 13:55:21 +0200158(To do that, copy the signature, put a ``*`` in front of the function
Laurens Van Houtvenefa5cfb2014-06-23 13:51:35 +0200159name and wrap it in parens, and then put ``= NULL`` at the end).
160
161Note how types don't need to be conditionally defined, as long as all
162the necessarily typedefs are in place.
163
164Finally, add an entry to ``CONDITIONAL_NAMES`` with all of the things
165you want to conditionally export::
166
167 CONDITIONAL_NAMES = {
168 ...
169 "Cryptography_HAS_QUANTUM_TRANSMOGRIFICATION": [
170 "QM_TRANSMOGRIFICATION_ALIGNMENT_LEFT",
171 "QM_TRANSMOGRIFICATION_ALIGNMENT_RIGHT",
172 "QM_transmogrify"
173 ]
174 }
175
176Caveats
177~~~~~~~
178
179Sometimes, a set of loosely related features are added in the same
180version, and it's impractical to create ``#ifdef`` statements for each
181one. In that case, it may make sense to either check for a particular
Laurens Van Houtven1c07ddf2014-06-23 13:55:27 +0200182version. For example, to check for OpenSSL 1.0.0 or newer::
Laurens Van Houtvenefa5cfb2014-06-23 13:51:35 +0200183
184 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
185
Laurens Van Houtven260e8872014-06-23 16:22:32 +0200186Sometimes, the version of a library on a particular platform will have
Laurens Van Houtvenefa5cfb2014-06-23 13:51:35 +0200187features that you thought it wouldn't, based on its version.
188Occasionally, packagers appear to ship arbitrary VCS checkouts. As a
189result, sometimes you may have to add separate ``#ifdef`` statements
190for particular features. This kind of issue is typically only caught
191by running the tests on a wide variety of systems, which is the job of
192our continuous integration infrastructure.