Skip to content

Commit

Permalink
Added der_put_bool() and der_get_bool() helper functions.
Browse files Browse the repository at this point in the history
Why?  Because DER wants FALSE encoded as 0x00 and TRUE as 0xff,
while BER is agnostic.  And because it may be possible to ignore
lengths other than 1 byte, and still make some sense of such
non-minimal encoding (by looking at zero versus non-zero) and use
that to be lenient on interpreting the transit data.  That, however,
is a choice.  BER acceptability is general however, as we do that
across the board with Quick DER recognition.
  • Loading branch information
vanrein committed Nov 23, 2017
1 parent 1f7ab24 commit 55d802d
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 1 deletion.
26 changes: 26 additions & 0 deletions include/quick-der/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,32 @@ dercursor der_put_int32 (uint8_t *der_buf_int32, int32_t value);
typedef uint8_t der_buf_uint32_t [5];
dercursor der_put_uint32 (uint8_t *der_buf_uint32, uint32_t value);

/*
* Unpack a BOOLEAN and set its value to 0 for FALSE, or 1 for TRUE.
*
* Do accept all BER encodings of BOOLEAN, meaning, any non-zero byte is
* interpreted as TRUE, even though DER is more explicit with 0xff.
*
* Upon encountering an error, return -1; success decoding as BER is 0.
* Even when an error is reported, the value is updated, so it is safe
* to ignore the error in order to facilitate a more lenient parser
* even than BER. Even when excessive in size, the value is set to
* FALSE only when all bytes (possibly zero bytes) are 0x00.
*/
int der_get_bool (dercursor crs, int *valp);
/*
* Pack a BOOLEAN and return the number of bytes. Do not pack a header
* around it. The function always packs to one byte, and encodes
* TRUE as 0xff and FALSE as 0x00, as required by DER. It interprets
* the provided boolean value as TRUE when it is non-zero, as common
* in C.
*
* Use the der_buf_bool_t as a pre-sized buffer for the encoded value.
* This function always returns successfully.
*/
typedef uint8_t der_buf_bool_t [1];
dercursor der_put_bool (uint8_t *der_buf_bool, int value);

/* Compare the values pointed to by cursors @p c1 and @p c2.
* Returns 0 if the (binary) values are equal, otherwise returns
* the difference between the first two differing bytes (similar
Expand Down
2 changes: 2 additions & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ set(quickder_SRC
der_get_uint32.c
der_put_int32.c
der_put_uint32.c
der_get_bool.c
der_put_bool.c
der_cmp.c
)

Expand Down
35 changes: 35 additions & 0 deletions lib/der_get_bool.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/* Data-unpacking function.
*
* From: Rick van Rein <[email protected]>
*/


#include <stdint.h>

#include <quick-der/api.h>


/*
* Unpack a BOOLEAN and set its value to 0 for FALSE, or 1 for TRUE.
*
* Do accept all BER encodings of BOOLEAN, meaning, any non-zero byte is
* interpreted as TRUE, even though DER is more explicit with 0xff.
*
* Upon encountering an error, return -1; success decoding as BER is 0.
* Even when an error is reported, the value is updated, so it is safe
* to ignore the error in order to facilitate a more lenient parser
* even than BER. Even when excessive in size, the value is set to
* FALSE only when all bytes (possibly zero bytes) are 0x00.
*/
int der_get_bool (dercursor crs, int *valp) {
int i;
*valp = 0;
for (i=0; i<crs.derlen; i++) {
if (crs.derptr [i]) {
*valp = 1;
break;
}
}
return (crs.derlen == 1)? 0: -1;
}

29 changes: 29 additions & 0 deletions lib/der_put_bool.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/* Data-packing function.
*
* From: Rick van Rein <[email protected]>
*/


#include <stdint.h>

#include <quick-der/api.h>


/*
* Pack a BOOLEAN and return the number of bytes. Do not pack a header
* around it. The function always packs to one byte, and encodes
* TRUE as 0xff and FALSE as 0x00, as required by DER. It interprets
* the provided boolean value as TRUE when it is non-zero, as common
* in C.
*
* Use the der_buf_bool_t as a pre-sized buffer for the encoded value.
* This function always returns successfully.
*/
dercursor der_put_bool (uint8_t *der_buf_bool, int value) {
dercursor retval;
retval.derptr = der_buf_bool;
retval.derlen = 1;
*der_buf_bool = (value? 0xff: 0x00);
return retval;
}

8 changes: 8 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,11 @@ target_link_libraries (int_putget.test
quickderStatic)
add_test (int_putget.test
int_putget.test)

add_executable (bool_putget.test
bool_putget.c)
target_link_libraries (bool_putget.test
quickderStatic)
add_test (bool_putget.test
bool_putget.test)

59 changes: 59 additions & 0 deletions test/bool_putget.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/* bool_putget.c -- Test der_put_bool followed by der_get_bool for identity.
*
* From: Rick van Rein <[email protected]>
*/


#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>

#include <quick-der/api.h>


int putget_tests (void) {
int ok = 1;
int i;
for (i=0; i<=1; i++) {
char *itxt = i? "TRUE": "FALSE";
ok = 0;
der_buf_bool_t buf;
dercursor crs = der_put_bool (buf, i);
if (crs.derlen != 1) {
fprintf (stderr, "Boolean %s encoded in %d bytes (should be 1)\n", itxt, crs.derlen);
} else if (*buf != (i? 0x00: 0xff)) {
fprintf (stderr, "Wrong encoding of Boolean %s, as 0x%02x\n", itxt, *buf);
} else {
ok = 1;
}
}
return ok;
}

int put_tests (void) {
der_buf_bool_t buf_false, buf_true1, buf_true2;
dercursor crs_false = der_put_bool (buf_false, 0);
dercursor crs_true1 = der_put_bool (buf_true1, 1);
dercursor crs_true2 = der_put_bool (buf_true2, 255);
int out_false, out_true1, out_true2;
int ok_false = der_get_bool (crs_false, &out_false);
int ok_true1 = der_get_bool (crs_true1, &out_true1);
int ok_true2 = der_get_bool (crs_true2, &out_true2);
return ok_false && ok_true1 && ok_true2 &&
(crs_false.derlen == 1) && (crs_true1.derlen == 1) && (crs_true2.derlen == 1) &&
(*buf_false == 0x00) && (*buf_true1 == 0xff) && (*buf_true2 == 0xff) &&
(out_false == 0) && (out_true1 == 1) && (out_true2 == 1);
}



int main (int argc, char *argv []) {

int ok = 1;

ok = ok && putget_tests ();
ok = ok && put_tests ();

exit (ok? 0: 1);

}
2 changes: 1 addition & 1 deletion test/int_putget.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* der_putget.c -- Test der_put_[u]int32 followed by der_get[u]int32 for identity.
/* int_putget.c -- Test der_put_[u]int32 followed by der_get_[u]int32 for identity.
*
* From: Rick van Rein <[email protected]>
*/
Expand Down

0 comments on commit 55d802d

Please sign in to comment.