1 /* -*- mode: c; c-file-style:"stroustrup"; -*- */
2 
3 /*
4  * Copyright (c) 2018 Mastercard
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include <config.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <assert.h>
24 #include <search.h>
25 
26 #include <openssl/bio.h>
27 #include <openssl/pem.h>
28 #include <openssl/x509.h>
29 
30 #include "pkcs11lib.h"
31 #include "wrappedkey_lexer.h"
32 #include "wrappedkey_parser.h"
33 
34 
35 /* wrappedKeyContext will hold information about wrapping/unwrapping keys
36 
37    several wrapping methods are supported:
38    - the regular wrapping methods ( PKCS#1, OAEP, CBC_PAD, AES_KEY_WRAP, AES_KEY_WRAP_PAD )
39    - envelope wrapping, where a private key (RSA) wraps a symmetric key, that in turn wraps any kind of key
40 
41    to support both models, the structure contains a small array where actual wrapped key info is maintained.
42 
43    ...
44    struct {
45        CK_BYTE_PTR wrapped_key_buffer;
46        CK_ULONG wrapped_key_len;
47        enum wrappingmethod wrapping_meth;
48    } key[2];
49    ...
50 
51    the first element is always for the outer key, which is used only for envelope wrapping.
52    the second element is either used as the inner key in envelope mode, or as the lone key for other wrapping algorithms.
53 
54  */
55 
56 
pkcs11_new_wrappedkeycontext(pkcs11Context * p11Context)57 wrappedKeyCtx *pkcs11_new_wrappedkeycontext(pkcs11Context *p11Context)
58 {
59     wrappedKeyCtx *ctx = NULL;
60 
61     if(p11Context) {
62 	ctx = calloc(1, sizeof (wrappedKeyCtx));
63 
64 	if(ctx==NULL) {
65 	    fprintf(stderr, "Error: not enough memory when allocating memory for wrappedKeyCtx\n");
66 	    goto error;
67 	}
68 
69 	ctx->p11Context = p11Context;
70 
71 	ctx->oaep_params = calloc( 1, sizeof(CK_RSA_PKCS_OAEP_PARAMS) );
72 	if(ctx->oaep_params == NULL) {
73 	    fprintf(stderr, "Error: not enough memory when allocating memory for CK_RSA_PKCS_OAEP_PARAMS of wrappedKeyCtx\n");
74 	    goto error;
75 	}
76 
77 	ctx->is_envelope = CK_FALSE;
78 
79 	ctx->wrpkattribs = pkcs11_new_attribcontext();
80 	if(ctx->wrpkattribs == NULL) {
81 	    fprintf(stderr, "Error: not enough memory when allocating memory for wrpkattribs member\n");
82 	    goto error;
83 	}
84 
85 	ctx->pubkattribs = pkcs11_new_attribcontext();
86 	if(ctx->pubkattribs == NULL) {
87 	    fprintf(stderr, "Error: not enough memory when allocating memory for pubkattribs member\n");
88 	    goto error;
89 	}
90     }
91 
92     return ctx;
93 
94 error:
95     if(ctx) {
96 	if(ctx->wrpkattribs) pkcs11_free_attribcontext(ctx->wrpkattribs);
97 	if(ctx->pubkattribs) pkcs11_free_attribcontext(ctx->pubkattribs);
98 	pkcs11_free_wrappedkeycontext(ctx);
99     }
100     return NULL;
101 }
102 
pkcs11_wctx_free_mechanisms(wrappedKeyCtx * wctx)103 inline void pkcs11_wctx_free_mechanisms(wrappedKeyCtx *wctx)
104 {
105     if(wctx && wctx->allowedmechs) {
106 	free(wctx->allowedmechs);
107 	wctx->allowedmechs = NULL;
108 	wctx->allowedmechs_len = 0;
109     }
110 }
111 
112 /* to use only for transfer of ownership */
pkcs11_wctx_forget_mechanisms(wrappedKeyCtx * wctx)113 inline void pkcs11_wctx_forget_mechanisms(wrappedKeyCtx *wctx)
114 {
115     if(wctx && wctx->allowedmechs) {
116 	wctx->allowedmechs = NULL;
117 	wctx->allowedmechs_len = 0;
118     }
119 }
120 
pkcs11_wctx_get_allowed_mechanisms(wrappedKeyCtx * ctx)121 inline CK_MECHANISM_TYPE_PTR pkcs11_wctx_get_allowed_mechanisms(wrappedKeyCtx *ctx)
122 {
123     return ctx ? ctx->allowedmechs : NULL;
124 }
125 
pkcs11_wctx_get_allowed_mechanisms_len(wrappedKeyCtx * ctx)126 inline size_t pkcs11_wctx_get_allowed_mechanisms_len(wrappedKeyCtx *ctx)
127 {
128     return ctx ? ctx->allowedmechs_len : 0;
129 }
130 
131 
pkcs11_free_wrappedkeycontext(wrappedKeyCtx * wctx)132 void pkcs11_free_wrappedkeycontext(wrappedKeyCtx *wctx)
133 {
134 
135     if( wctx ) {
136 
137 	/* free up wrappingkeylabel */
138 	if(wctx->wrappingkeylabel) {
139 	    free(wctx->wrappingkeylabel);
140 	    wctx->wrappingkeylabel= NULL ;
141 	}
142 
143 	/* free up wrappedkeylabel */
144 	if(wctx->wrappedkeylabel) {
145 	    free(wctx->wrappedkeylabel);
146 	    wctx->wrappedkeylabel = NULL ;
147 	}
148 
149 	/* free up filename */
150 	if(wctx->filename) {
151 	    free(wctx->filename);
152 	    wctx->filename = NULL;
153 	}
154 
155 	/* free up allowed mechanisms array */
156 	pkcs11_wctx_free_mechanisms(wctx);
157 
158 	/* free up buffers */
159 	int i;
160 	for(i=0; i<2; ++i) {
161 	    if(wctx->key[i].wrapped_key_buffer) {
162 		free(wctx->key[i].wrapped_key_buffer);
163 		wctx->key[i].wrapped_key_buffer = NULL;
164 		wctx->key[i].wrapped_key_len = 0;
165 	    }
166 	}
167 
168 	/* free up OAEP structure */
169 	if(wctx->oaep_params) {
170 	    if(wctx->oaep_params->pSourceData) {
171 		free(wctx->oaep_params->pSourceData);
172 		wctx->oaep_params->pSourceData=NULL;
173 		wctx->oaep_params->ulSourceDataLen=0L;
174 	    }
175 	    free(wctx->oaep_params);
176 	    wctx->oaep_params = NULL;
177 	}
178 
179 	/* free up iv member */
180 	if(wctx->aes_params.iv) {
181 	    free(wctx->aes_params.iv);
182 	    wctx->aes_params.iv = NULL;
183 	    wctx->aes_params.iv_len = 0L;
184 	}
185 
186 	/* free up pubk_pem_buffer */
187 	if(wctx->pubk_buffer) {
188 	    free(wctx->pubk_buffer);
189 	    wctx->pubk_buffer = NULL;
190 	    wctx->pubk_len=0;
191 	}
192 
193 	/* free up wrappedkeyattribs */
194 	if(wctx->wrpkattribs) {
195 	    pkcs11_free_attribcontext(wctx->wrpkattribs);
196 	    wctx->wrpkattribs = NULL;
197 	}
198 
199 	/* free up pubkeyattribs */
200 	if(wctx->pubkattribs) {
201 	    pkcs11_free_attribcontext(wctx->pubkattribs);
202 	    wctx->pubkattribs = NULL;
203 	}
204 
205 	free(wctx);		/* eventually free up context mem */
206     }
207 }
208