miniroon

Simplistic macaroon-based authorization for Unix systems
git clone https://ccx.te2000.cz/git/miniroon
Log | Files | Refs

decode.c (2070B)


      1 #include <stdint.h>
      2 
      3 #include "verify_common.h"
      4 #include "decode.h"
      5 #include "header.h"
      6 #include "secret.h"
      7 #include "hmac_sha2_256.h"
      8 
      9 miniroon_error miniroon_decode(miniroon_data *md, const bytebuffer encoded) {
     10   miniroon_data_init(md);
     11   netstring_chunk c;
     12   netstring_chunk_init(&c, encoded);
     13 
     14   if(!netstring_chunk_next(&c)) {
     15     return miniroon_err1(MINIROON_EDEC_NO_HEADER, "Mising miniroon header");
     16   }
     17   if(parse_header(&md->hdr, c.inner) != MINIROON_OK) {
     18     return miniroon_current_error;
     19   }
     20   // header should be verified by now, we can start hashing
     21   uint8_t hmac_data[MINIROON_HMAC_SIZE];
     22   bytebuffer hmac_bb = {hmac_data, MINIROON_HMAC_SIZE};
     23   read_secret(hmac_bb);
     24   // dbg_print_bb1("Secret", hmac_bb);
     25   MINIROON_HMAC_FUNC(hmac_bb, c.inner, hmac_bb);
     26   // dbg_print_bb1("Signature update", hmac_bb);
     27 
     28   if(!netstring_chunk_next(&c)) {
     29     return miniroon_err1(MINIROON_EDEC_NO_BODY, "Mising miniroon body");
     30   }
     31   netstring_chunk body;
     32   netstring_chunk_init(&body, c.inner);
     33 
     34   while(netstring_chunk_next(&body)) {
     35     dbg_print_bb1("Got caveat", body.inner);
     36     if(md->caveat_count >= MAX_CAVEATS) {
     37       return miniroon_err1(MINIROON_EDEC_MANY_CAVEATS, "Too many caveats");
     38     }
     39     md->caveats[md->caveat_count++] = body.inner;
     40     MINIROON_HMAC_FUNC(hmac_bb, body.inner, hmac_bb);
     41     // dbg_print_bb1("Signature update", hmac_bb);
     42   }
     43 
     44   if(!netstring_chunk_next(&c)) {
     45     return miniroon_err1(MINIROON_EDEC_NO_SIGNATURE, "Mising miniroon signature");
     46   }
     47   dbg_print_bb1("Got signature", c.inner);
     48   if(c.inner.len != MINIROON_HMAC_SIZE) {
     49     return miniroon_err1(MINIROON_EDEC_INV_SIGNATURE, "Invalid miniroon signature length");
     50   }
     51   /* constant time hash compare */
     52   uint8_t bitdiff = 0;
     53   for(size_t i=0; i<MINIROON_HMAC_SIZE; i++) {
     54     bitdiff |= hmac_data[i] ^ c.inner.data[i];
     55   }
     56   if(netstring_chunk_next(&c)) {
     57     return miniroon_err1(MINIROON_EDEC_EXTRA, "Extraneous data in miniroon");
     58   }
     59   if(bitdiff) {
     60     return miniroon_err1(MINIROON_EDEC_BAD_SIGNATURE, "Bad miniroon signature");
     61   }
     62 
     63   return MINIROON_OK;
     64 }