4 Description: stdio-based routines to get cert info from user.
8 Copyright: © Copyright 2002 Apple Computer, Inc. All rights reserved.
10 Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
11 Computer, Inc. ("Apple") in consideration of your agreement to
12 the following terms, and your use, installation, modification
13 or redistribution of this Apple software constitutes acceptance
14 of these terms. If you do not agree with these terms, please
15 do not use, install, modify or redistribute this Apple software.
17 In consideration of your agreement to abide by the following
18 terms, and subject to these terms, Apple grants you a personal,
19 non-exclusive license, under Apple's copyrights in this
20 original Apple software (the "Apple Software"), to use,
21 reproduce, modify and redistribute the Apple Software, with
22 or without modifications, in source and/or binary forms;
23 provided that if you redistribute the Apple Software in
24 its entirety and without modifications, you must retain
25 this notice and the following text and disclaimers in all
26 such redistributions of the Apple Software. Neither the
27 name, trademarks, service marks or logos of Apple Computer,
28 Inc. may be used to endorse or promote products derived from the
29 Apple Software without specific prior written permission from
30 Apple. Except as expressly stated in this notice, no other
31 rights or licenses, express or implied, are granted by Apple
32 herein, including but not limited to any patent rights that
33 may be infringed by your derivative works or by other works
34 in which the Apple Software may be incorporated.
36 The Apple Software is provided by Apple on an "AS IS" basis.
37 APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
38 WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT,
39 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
40 REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE
41 OR IN COMBINATION WITH YOUR PRODUCTS.
43 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT,
44 INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
45 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION
48 AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
49 AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING
50 NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE
51 HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
55 #include <Security/x509defs.h>
56 #include <Security/oidsattr.h>
57 #include <Security/oidscert.h>
58 #include <Security/oidsalg.h>
63 #include <cdsaUtils/cdsaUtils.h>
64 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
70 printf("%s returned %d\n", errStr
, (int)ortn
);
76 * -- guaranteed no buffer overflow
77 * -- guaranteed NULL-terminated string
78 * -- handles empty string (i.e., response is just CR) properly
88 for(dex
=0; dex
<bufSize
-1; dex
++) {
106 * Prompt and safe getString.
108 void getStringWithPrompt(
109 const char *prompt
, // need not end in newline
114 printf("%s", prompt
);
116 getString(buf
, bufSize
);
119 static const NameOidInfo nameOidInfo
[MAX_NAMES
] =
121 { &CSSMOID_CommonName
, "Common Name ", "www.apple.com"},
122 { &CSSMOID_CountryName
, "Country ", "US"},
123 { &CSSMOID_OrganizationName
, "Organization ", "Apple Computer, Inc."},
124 { &CSSMOID_OrganizationalUnitName
, "Organization Unit", "Apple Data Security"},
125 { &CSSMOID_StateProvinceName
, "State/Province ", "California" }
128 static const char *oidToDesc(
133 for(dex
=0; dex
<MAX_NAMES
; dex
++) {
134 if(cuCompareCssmData(oid
, nameOidInfo
[dex
].oid
)) {
135 return nameOidInfo
[dex
].description
;
138 printf("oidToDesc error!\n");
145 CSSM_APPLE_TP_NAME_OID
*subjectNames
, // size MAX_NAMES mallocd by caller
146 uint32
*numNames
) // RETURNED
149 const NameOidInfo
*nameOidIn
;
150 CSSM_APPLE_TP_NAME_OID
*nameOidOut
= subjectNames
;
156 memset(subjectNames
, 0, MAX_NAMES
* sizeof(CSSM_APPLE_TP_NAME_OID
));
158 printf("\nYou will now specify the various components of the certificate's\n"
159 "Relative Distinguished Name (RDN). An RDN has a number of \n"
160 "components, all of which are optional, but at least one of \n"
161 "which must be present. \n\n"
162 "Note that if you are creating a certificate for use in an \n"
163 "SSL/TLS server, the Common Name component of the RDN must match\n"
164 "exactly the host name of the server. This must not be an IP\n"
165 "address, but the actual domain name, e.g. www.apple.com.\n\n"
166 "Entering a CR for a given RDN component results in no value for\n"
167 "that component.\n\n");
169 nameOidOut
= subjectNames
;
171 for(dex
=0; dex
<MAX_NAMES
; dex
++) {
172 nameOidIn
= &nameOidInfo
[dex
];
174 printf("%s (e.g, %s) : ",
175 nameOidIn
->description
, nameOidIn
->example
);
177 getString(resp
, sizeof(resp
));
178 if(resp
[0] != '\0') {
179 unsigned len
= strlen(resp
) + 1;
180 nameOidOut
->string
= (char *)malloc(len
);
181 strcpy((char *)nameOidOut
->string
, resp
);
182 nameOidOut
->oid
= nameOidIn
->oid
;
188 printf("\nYou must enter at least one value RDN component.\n\n");
191 printf("\nYou have specified:\n");
192 for(dex
=0; dex
<outNames
; dex
++) {
193 nameOidOut
= &subjectNames
[dex
];
194 printf(" %s : %s\n", oidToDesc(nameOidOut
->oid
), nameOidOut
->string
);
196 getStringWithPrompt("Is this OK (y/anything)? ", resp
, sizeof(resp
));
202 *numNames
= outNames
;
206 * Free strings mallocd in getNameOids.
209 CSSM_APPLE_TP_NAME_OID
*subjectNames
,
212 for(unsigned i
=0; i
<numNames
; i
++) {
213 if(subjectNames
[i
].string
) {
214 free((char *)subjectNames
[i
].string
);
219 /* key size verifier - one for each key alg */
221 static bool rsaKeySizeVerify(
233 static bool dsaKeySizeVerify(
236 return((keySize
>= 512) & (keySize
<= 2048));
239 static bool feeKeySizeVerify(
252 typedef bool (*keySizeVerifyFcn
)(unsigned keySize
);
254 /* map between algorithms, string, char selector, OID */
255 typedef struct _AlgInfo
{
259 const CSSM_OID
*oid
; // only for signatures
260 uint32 defaultKeySize
; // only for keys
261 char *keyRangeString
; // only for keys
262 const struct _AlgInfo
*sigAlgInfo
; // only for keys
263 keySizeVerifyFcn vfyFcn
; // only for keys
267 * Note: CSSM_ALGID_MD2WithRSA does not work due to an inimplemented
268 * Security Server feature. Even though CSP nad CL support this, we
269 * don't really want to provide this capability anyway - it's a known
270 * insecure digest algorithm.
272 static const AlgInfo rsaSigAlgInfo
[] =
274 { CSSM_ALGID_MD5WithRSA
, "RSA with MD5", '5', &CSSMOID_MD5WithRSA
},
275 // { CSSM_ALGID_MD2WithRSA, "RSA with MD2", '2', &CSSMOID_MD2WithRSA},
276 { CSSM_ALGID_SHA1WithRSA
, "RSA with SHA1", 's', &CSSMOID_SHA1WithRSA
},
277 { CSSM_ALGID_NONE
, NULL
, 0 }
280 static const AlgInfo feeSigAlgInfo
[] =
282 { CSSM_ALGID_FEE_MD5
, "FEE with MD5", '5', &CSSMOID_APPLE_FEE_MD5
},
283 { CSSM_ALGID_FEE_SHA1
, "FEE with SHA1", 's', &CSSMOID_APPLE_FEE_SHA1
},
284 { CSSM_ALGID_SHA1WithECDSA
, "ECDSA/SHA1", 'e', &CSSMOID_APPLE_ECDSA
},
285 { CSSM_ALGID_NONE
, NULL
, 0, NULL
}
288 static const AlgInfo dsaSigAlgInfo
[] =
290 { CSSM_ALGID_SHA1WithDSA
, "DSA with SHA1", 's', &CSSMOID_APPLE_FEE_MD5
},
291 { CSSM_ALGID_NONE
, NULL
, 0, NULL
}
294 static const AlgInfo keyAlgInfo
[] =
296 { CSSM_ALGID_RSA
, "RSA", 'r', NULL
, 512, "512..2048",
297 rsaSigAlgInfo
, rsaKeySizeVerify
},
298 { CSSM_ALGID_DSA
, "DSA", 'd', NULL
, 512, "512..2048",
299 dsaSigAlgInfo
, dsaKeySizeVerify
},
300 { CSSM_ALGID_FEE
, "FEE", 'f', NULL
, 128, "128, 161, 192",
301 feeSigAlgInfo
, feeKeySizeVerify
},
302 { CSSM_ALGID_NONE
, NULL
, 0, NULL
}
306 /* map a char response to an element of an AlgInfo array */
307 static const AlgInfo
*algInfoForSelect(
308 const AlgInfo
*algInfo
, // NULL terminated
311 while(algInfo
->str
!= NULL
) {
312 if(algInfo
->selector
== c
) {
321 /* map a CSSM_ALGORITHM to an entry in keyAlgInfo[] */
322 static const AlgInfo
*algInfoForAlg(
325 const AlgInfo
*algInfo
= keyAlgInfo
;
326 while(algInfo
->str
!= NULL
) {
327 if(algInfo
->alg
== alg
) {
336 /* get key size and algorithm for subject key */
338 CSSM_ALGORITHMS
&keyAlg
,
339 uint32
&keySizeInBits
)
342 const AlgInfo
*keyInfo
;
343 const AlgInfo
*tempInfo
;
345 /* get a key algorithm */
346 printf("\nPlease specify parameters for the key pair you will generate.\n\n");
348 /* break when we get a valid key algorithm */
349 tempInfo
= keyAlgInfo
;
350 while(tempInfo
->str
!= NULL
) {
351 printf(" %c %s\n", tempInfo
->selector
, tempInfo
->str
);
354 getStringWithPrompt("\nSelect key algorithm by letter: ", resp
, sizeof(resp
));
355 if(resp
[0] == '\0') {
356 printf("***There is no default. Please choose a key algorithm.\n");
359 keyInfo
= algInfoForSelect(keyAlgInfo
, resp
[0]);
366 /* until we get a valid key size */
367 printf("\nValid key sizes for %s are %s; default is %u\n",
368 keyInfo
->str
, keyInfo
->keyRangeString
, (unsigned)keyInfo
->defaultKeySize
);
369 getStringWithPrompt("Enter key size in bits or CR for default: ",
371 if(resp
[0] == '\0') {
372 keySizeInBits
= keyInfo
->defaultKeySize
;
375 keySizeInBits
= atoi(resp
);
377 if(keyInfo
->vfyFcn(keySizeInBits
)) {
378 printf("\nYou have selected algorithm %s, key size %u bits.\n",
379 keyInfo
->str
, (unsigned)keySizeInBits
);
380 getStringWithPrompt("OK (y/anything)? ", resp
, sizeof(resp
));
386 printf("***%u is not a legal key size for algorithm %s.\n",
387 (unsigned)keySizeInBits
, keyInfo
->str
);
390 keyAlg
= keyInfo
->alg
;
393 /* given a signing key, obtain signing algorithm (int and oid format) */
395 const CSSM_KEY
*signingKey
,
396 CSSM_ALGORITHMS
&sigAlg
,
397 const CSSM_OID
* &sigOid
)
400 const AlgInfo
*keyInfo
;
401 const AlgInfo
*tempInfo
;
402 const AlgInfo
*sigInfoArray
;
403 const AlgInfo
*sigInfo
;
405 keyInfo
= algInfoForAlg(signingKey
->KeyHeader
.AlgorithmId
);
406 if(keyInfo
== NULL
) {
407 printf("***Signing key has unknown algorithm (%u).\n",
408 (unsigned)signingKey
->KeyHeader
.AlgorithmId
);
411 sigInfoArray
= keyInfo
->sigAlgInfo
;
412 printf("\nPlease specify the algorithm with which your certificate will be "
415 /* break when we get a valid sig algorithm */
416 tempInfo
= sigInfoArray
;
417 while(tempInfo
->str
!= NULL
) {
418 printf(" %c %s\n", tempInfo
->selector
, tempInfo
->str
);
421 getStringWithPrompt("\nSelect signature algorithm by letter: ",
423 if(resp
[0] == '\0') {
424 printf("***There is no default. Please choose a signature algorithm.\n");
427 sigInfo
= algInfoForSelect(sigInfoArray
, resp
[0]);
428 if(sigInfo
== NULL
) {
429 printf("Try again.\n");
432 printf("\nYou have selected algorithm %s.\n", sigInfo
->str
);
433 getStringWithPrompt("OK (y/anything)? ", resp
, sizeof(resp
));
438 sigAlg
= sigInfo
->alg
;
439 sigOid
= sigInfo
->oid
;
443 CU_KeyUsage
getKeyUsage(bool isRoot
)
449 /* root HAS to be capable of signing */
450 prompt
= "Enter cert/key usage (s=signing, b=signing AND encrypting): ";
453 prompt
= "Enter cert/key usage (s=signing, e=encrypting, b=both): ";
456 getStringWithPrompt(prompt
, resp
, sizeof(resp
));
459 return kKeyUseSigning
;
464 return kKeyUseEncrypting
;
466 return kKeyUseSigning
| kKeyUseEncrypting
;