1 /*!
2  * Copyrights
3  *
4  * Portions created or assigned to Cisco Systems, Inc. are
5  * Copyright (c) 2014-2016 Cisco Systems, Inc.  All Rights Reserved.
6  */
7 
8 #include <stdlib.h>
9 #include <jansson.h>
10 #include "cjose/header.h"
11 #include "include/header_int.h"
12 
13 const char *CJOSE_HDR_ALG = "alg";
14 const char *CJOSE_HDR_ALG_NONE = "none";
15 const char *CJOSE_HDR_ALG_ECDH_ES = "ECDH-ES";
16 const char *CJOSE_HDR_ALG_RSA_OAEP = "RSA-OAEP";
17 const char *CJOSE_HDR_ALG_RSA1_5 = "RSA1_5";
18 const char *CJOSE_HDR_ALG_A128KW = "A128KW";
19 const char *CJOSE_HDR_ALG_A192KW = "A192KW";
20 const char *CJOSE_HDR_ALG_A256KW = "A256KW";
21 const char *CJOSE_HDR_ALG_DIR = "dir";
22 const char *CJOSE_HDR_ALG_PS256 = "PS256";
23 const char *CJOSE_HDR_ALG_PS384 = "PS384";
24 const char *CJOSE_HDR_ALG_PS512 = "PS512";
25 const char *CJOSE_HDR_ALG_RS256 = "RS256";
26 const char *CJOSE_HDR_ALG_RS384 = "RS384";
27 const char *CJOSE_HDR_ALG_RS512 = "RS512";
28 const char *CJOSE_HDR_ALG_HS256 = "HS256";
29 const char *CJOSE_HDR_ALG_HS384 = "HS384";
30 const char *CJOSE_HDR_ALG_HS512 = "HS512";
31 const char *CJOSE_HDR_ALG_ES256 = "ES256";
32 const char *CJOSE_HDR_ALG_ES384 = "ES384";
33 const char *CJOSE_HDR_ALG_ES512 = "ES512";
34 
35 const char *CJOSE_HDR_ENC = "enc";
36 const char *CJOSE_HDR_ENC_A256GCM = "A256GCM";
37 const char *CJOSE_HDR_ENC_A128CBC_HS256 = "A128CBC-HS256";
38 const char *CJOSE_HDR_ENC_A192CBC_HS384 = "A192CBC-HS384";
39 const char *CJOSE_HDR_ENC_A256CBC_HS512 = "A256CBC-HS512";
40 
41 const char *CJOSE_HDR_CTY = "cty";
42 
43 const char *CJOSE_HDR_KID = "kid";
44 
45 const char *CJOSE_HDR_EPK = "epk";
46 
47 const char *CJOSE_HDR_APU = "apu";
48 const char *CJOSE_HDR_APV = "apv";
49 
50 ////////////////////////////////////////////////////////////////////////////////
cjose_header_new(cjose_err * err)51 cjose_header_t *cjose_header_new(cjose_err *err)
52 {
53     cjose_header_t *retval = (cjose_header_t *)json_object();
54     if (NULL == retval)
55     {
56         CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
57     }
58     return retval;
59 }
60 
61 ////////////////////////////////////////////////////////////////////////////////
cjose_header_retain(cjose_header_t * header)62 cjose_header_t *cjose_header_retain(cjose_header_t *header)
63 {
64     if (NULL != header)
65     {
66         header = (cjose_header_t *)json_incref((json_t *)header);
67     }
68     return header;
69 }
70 
71 ////////////////////////////////////////////////////////////////////////////////
cjose_header_release(cjose_header_t * header)72 void cjose_header_release(cjose_header_t *header)
73 {
74     if (NULL != header)
75     {
76         json_decref((json_t *)header);
77     }
78 }
79 
80 ////////////////////////////////////////////////////////////////////////////////
cjose_header_set(cjose_header_t * header,const char * attr,const char * value,cjose_err * err)81 bool cjose_header_set(cjose_header_t *header, const char *attr, const char *value, cjose_err *err)
82 {
83     if (NULL == header || NULL == attr || NULL == value)
84     {
85         CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
86         return false;
87     }
88 
89     json_t *value_obj = json_string(value);
90     if (NULL == value_obj)
91     {
92         CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
93         return false;
94     }
95 
96     json_object_set_new((json_t *)header, attr, value_obj);
97 
98     return true;
99 }
100 
101 ////////////////////////////////////////////////////////////////////////////////
cjose_header_get(cjose_header_t * header,const char * attr,cjose_err * err)102 const char *cjose_header_get(cjose_header_t *header, const char *attr, cjose_err *err)
103 {
104     if (NULL == header || NULL == attr)
105     {
106         CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
107         return NULL;
108     }
109 
110     json_t *value_obj = json_object_get((json_t *)header, attr);
111     if (NULL == value_obj)
112     {
113         return NULL;
114     }
115 
116     return json_string_value(value_obj);
117 }
118 
119 ////////////////////////////////////////////////////////////////////////////////
cjose_header_set_raw(cjose_header_t * header,const char * attr,const char * value,cjose_err * err)120 bool cjose_header_set_raw(cjose_header_t *header, const char *attr, const char *value, cjose_err *err)
121 {
122     if (NULL == header || NULL == attr || NULL == value)
123     {
124         CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
125         return false;
126     }
127 
128     json_error_t j_err;
129     json_t *value_obj = json_loads(value, 0, &j_err);
130     if (NULL == value_obj)
131     {
132         // unfortunately, it's not possible to tell whether the error is due
133         // to syntax, or memory shortage. See https://github.com/akheron/jansson/issues/352
134         CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
135         return false;
136     }
137 
138     json_object_set_new((json_t *)header, attr, value_obj);
139 
140     return true;
141 }
142 
143 ////////////////////////////////////////////////////////////////////////////////
cjose_header_get_raw(cjose_header_t * header,const char * attr,cjose_err * err)144 char *cjose_header_get_raw(cjose_header_t *header, const char *attr, cjose_err *err)
145 {
146     if (NULL == header || NULL == attr)
147     {
148         CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
149         return NULL;
150     }
151 
152     json_t *value_obj = json_object_get((json_t *)header, attr);
153     if (NULL == value_obj)
154     {
155         return NULL;
156     }
157 
158     return json_dumps(value_obj, JSON_COMPACT);
159 }
160