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
20 #include <config.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <stdarg.h>
25 #include <ctype.h>
26 #include "pkcs11lib.h"
27
28
29 /* high-level search functions */
30
pkcs11_mv_objects(pkcs11Context * p11Context,char * src,char * dest,int interactive,int verbose)31 int pkcs11_mv_objects(pkcs11Context *p11Context, char *src, char *dest, int interactive, int verbose)
32 {
33
34 int rv=0;
35 pkcs11Search *search=NULL;
36 pkcs11IdTemplate *idtmpl=NULL;
37 char *destlabel;
38 typedef enum { all, cert, pubk, prvk, seck, data } objtype;
39
40 objtype whatsrc = all, whatdest = all;
41
42
43
44 /* check source */
45
46 if(strncasecmp("prvk/", src, 5) ==0 ) { /* private key case */
47 whatsrc = prvk;
48 } else if (strncasecmp("pubk/", src, 5) ==0 ) { /* public key case */
49 whatsrc = pubk;
50 } else if (strncasecmp("seck/", src, 5) ==0 ) { /* secret key case */
51 whatsrc = seck;
52 } else if (strncasecmp("cert/", src, 5) ==0 ) { /* cert case */
53 whatsrc = cert;
54 } else if (strncasecmp("data/", src, 5) ==0 ) { /* data case */
55 whatsrc = cert;
56 } else { /* generic case */
57 whatsrc = all;
58 }
59
60
61 /* check dest */
62
63 if(strncasecmp("prvk/", dest, 5) ==0 ) { /* private key case */
64 whatdest = prvk;
65 destlabel = &dest[5];
66 } else if (strncasecmp("pubk/", dest, 5) ==0 ) { /* public key case */
67 whatdest = pubk;
68 destlabel = &dest[5];
69 } else if (strncasecmp("seck/", dest, 5) ==0 ) { /* secret key case */
70 whatdest = seck;
71 destlabel = &dest[5];
72 } else if (strncasecmp("cert/", dest, 5) ==0 ) { /* cert case */
73 whatdest = cert;
74 destlabel = &dest[5];
75 } else if (strncasecmp("data/", dest, 5) ==0 ) { /* data case */
76 whatdest = cert;
77 destlabel = &dest[5];
78 } else { /* generic case */
79 whatdest = all;
80 destlabel = dest;
81 }
82
83 /* compare src and dest */
84
85 if (whatsrc != whatdest) {
86 fprintf(stderr, "source and destination must be of the same kind. Use same prefix for both.\n");
87 rv = RC_ERROR_USAGE;
88 goto error;
89 }
90
91
92 switch(whatsrc) {
93
94 case all:
95 if(pkcs11_label_exists( p11Context, dest)) {
96 fprintf(stderr, "Error: at least one object already exists for destination label '%s'.\n", dest);
97 rv = RC_ERROR_OBJECT_EXISTS;
98 goto error;
99 }
100 break;
101
102 case prvk:
103 if(pkcs11_privatekey_exists( p11Context, dest)) {
104 fprintf(stderr,"Error: a private key already exists for destination label '%s'.\n", dest);
105 rv = RC_ERROR_OBJECT_EXISTS;
106 goto error;
107 }
108 break;
109
110 case pubk:
111 if(pkcs11_publickey_exists( p11Context, dest)) {
112 fprintf(stderr,"Error: a public key already exists for destination label '%s'.\n", dest);
113 rv = RC_ERROR_OBJECT_EXISTS;
114 goto error;
115 }
116 break;
117
118 case seck:
119 if(pkcs11_secretkey_exists( p11Context, dest)) {
120 fprintf(stderr,"Error: a secret key already exists for destination label '%s'.\n", dest);
121 rv = RC_ERROR_OBJECT_EXISTS;
122 goto error;
123 }
124 break;
125
126 case cert:
127 if(pkcs11_certificate_exists( p11Context, dest)) {
128 fprintf(stderr,"Error: a certificate already exists for destination label '%s'.\n", dest);
129 rv = RC_ERROR_OBJECT_EXISTS;
130 goto error;
131 }
132 break;
133
134 case data:
135 if(pkcs11_data_exists( p11Context, dest)) {
136 fprintf(stderr,"Error: a data file already exists for destination label '%s'.\n", dest);
137 rv = RC_ERROR_OBJECT_EXISTS;
138 goto error;
139 }
140 break;
141 }
142
143
144 idtmpl = pkcs11_make_idtemplate(src);
145
146 if(idtmpl && pkcs11_sizeof_idtemplate(idtmpl)>0) {
147
148 search = pkcs11_new_search_from_idtemplate( p11Context, idtmpl );
149
150 if(search) {
151
152 CK_OBJECT_HANDLE hndl=0;
153 int ok_to_move=1;
154 char choice;
155
156 while( (hndl = pkcs11_fetch_next(search))!=0 ) {
157
158 if(interactive) {
159 pkcs11AttrList *attrs;
160 char *prefixptr;
161 ok_to_move=0;
162
163 attrs = pkcs11_new_attrlist(p11Context,
164 _ATTR(CKA_CLASS),
165 _ATTR(CKA_LABEL),
166 _ATTR_END );
167
168 if( pkcs11_read_attr_from_handle (attrs, hndl) == true) {
169
170 CK_ATTRIBUTE_PTR oclass = pkcs11_get_attr_in_attrlist(attrs, CKA_CLASS);
171 CK_ATTRIBUTE_PTR olabel = pkcs11_get_attr_in_attrlist(attrs, CKA_LABEL);
172
173 if(oclass) {
174 switch(*(CK_OBJECT_CLASS *)(oclass->pValue)) {
175 case CKO_PRIVATE_KEY:
176 prefixptr = "prvk/";
177 break;
178
179 case CKO_PUBLIC_KEY:
180 prefixptr = "pubk/";
181 break;
182
183 case CKO_SECRET_KEY:
184 prefixptr = "seck/";
185 break;
186
187 case CKO_CERTIFICATE:
188 prefixptr = "cert/";
189 break;
190
191 case CKO_DATA:
192 prefixptr = "data/";
193 break;
194
195 default:
196 prefixptr = "othr/";
197 break;
198 }
199
200 fflush(stdin);
201
202 fprintf(stderr,
203 "move %s%.*s to %s%.*s ? (y/N)",
204 prefixptr,
205 (int)(olabel->ulValueLen),
206 (char *)(olabel->pValue),
207
208 prefixptr,
209 (int)strlen(destlabel),
210 destlabel );
211
212 fflush(stderr);
213
214 choice = getchar();
215 /* eat rest of the line + carriage return */
216 { int c; while( (c = getchar()) != EOF && c!= '\n'); }
217
218 if ( tolower(choice) == 'y') {
219 ok_to_move = 1;
220 }
221 }
222 }
223 pkcs11_delete_attrlist(attrs);
224 }
225
226
227 if(ok_to_move) {
228 CK_ATTRIBUTE nameattr;
229 CK_RV rc;
230 nameattr.type = CKA_LABEL;
231 nameattr.pValue = destlabel;
232 nameattr.ulValueLen = strlen(destlabel);
233
234 rc = pkcs11_setObjectAttribute( p11Context, hndl, &nameattr );
235
236 if(rc != CKR_OK) {
237 rv = RC_ERROR_PKCS11_API;
238 }
239 }
240
241 }
242 pkcs11_delete_search(search);
243 }
244 pkcs11_delete_idtemplate(idtmpl);
245 }
246 error:
247
248 return rv;
249 }
250
251 /* EOF */
252