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