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