2 * Copyright (c) 2002-2003 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please
7 * obtain a copy of the License at http://www.apple.com/publicsource and
8 * read it before using this file.
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
12 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
13 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
14 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
15 * Please see the License for the specific language governing rights and
16 * limitations under the License.
22 Description: stdio-based routines to get cert info from user.
28 #include <Security/x509defs.h>
29 #include <Security/oidsattr.h>
30 #include <Security/oidscert.h>
31 #include <Security/oidsalg.h>
36 #include <CdsaUtils/cuCdsaUtils.h>
37 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
43 printf("%s returned %d\n", errStr
, (int)ortn
);
49 * -- guaranteed no buffer overflow
50 * -- guaranteed NULL-terminated string
51 * -- handles empty string (i.e., response is just CR) properly
61 for(dex
=0; dex
<bufSize
-1; dex
++) {
83 * Prompt and safe getString.
85 void getStringWithPrompt(
86 const char *prompt
, // need not end in newline
92 getString(buf
, bufSize
);
95 static const NameOidInfo nameOidInfo
[MAX_NAMES
] =
97 { &CSSMOID_CommonName
, "Common Name ", "www.apple.com"},
98 { &CSSMOID_CountryName
, "Country ", "US"},
99 { &CSSMOID_OrganizationName
, "Organization ", "Apple Computer, Inc."},
100 { &CSSMOID_OrganizationalUnitName
, "Organization Unit", "Apple Data Security"},
101 { &CSSMOID_StateProvinceName
, "State/Province ", "California" }
104 static const char *oidToDesc(
109 for(dex
=0; dex
<MAX_NAMES
; dex
++) {
110 if(cuCompareCssmData(oid
, nameOidInfo
[dex
].oid
)) {
111 return nameOidInfo
[dex
].description
;
114 printf("oidToDesc error!\n");
121 CSSM_APPLE_TP_NAME_OID
*subjectNames
, // size MAX_NAMES mallocd by caller
122 uint32
*numNames
) // RETURNED
125 const NameOidInfo
*nameOidIn
;
126 CSSM_APPLE_TP_NAME_OID
*nameOidOut
= subjectNames
;
132 memset(subjectNames
, 0, MAX_NAMES
* sizeof(CSSM_APPLE_TP_NAME_OID
));
134 printf("\nYou will now specify the various components of the certificate's\n"
135 "Relative Distinguished Name (RDN). An RDN has a number of \n"
136 "components, all of which are optional, but at least one of \n"
137 "which must be present. \n\n"
138 "Note that if you are creating a certificate for use in an \n"
139 "SSL/TLS server, the Common Name component of the RDN must match\n"
140 "exactly the host name of the server. This must not be an IP\n"
141 "address, but the actual domain name, e.g. www.apple.com.\n\n"
142 "Entering a CR for a given RDN component results in no value for\n"
143 "that component.\n\n");
145 nameOidOut
= subjectNames
;
147 for(dex
=0; dex
<MAX_NAMES
; dex
++) {
148 nameOidIn
= &nameOidInfo
[dex
];
149 printf("%s (e.g, %s) : ",
150 nameOidIn
->description
, nameOidIn
->example
);
152 getString(resp
, sizeof(resp
));
153 if(resp
[0] != '\0') {
154 unsigned len
= strlen(resp
) + 1;
155 nameOidOut
->string
= (char *)malloc(len
);
156 strcpy((char *)nameOidOut
->string
, resp
);
157 nameOidOut
->oid
= nameOidIn
->oid
;
163 printf("\nYou must enter at least one value RDN component.\n\n");
166 printf("\nYou have specified:\n");
167 for(dex
=0; dex
<outNames
; dex
++) {
168 nameOidOut
= &subjectNames
[dex
];
169 printf(" %s : %s\n", oidToDesc(nameOidOut
->oid
), nameOidOut
->string
);
171 getStringWithPrompt("Is this OK (y/anything)? ", resp
, sizeof(resp
));
177 *numNames
= outNames
;
181 * Free strings mallocd in getNameOids.
184 CSSM_APPLE_TP_NAME_OID
*subjectNames
,
187 for(unsigned i
=0; i
<numNames
; i
++) {
188 if(subjectNames
[i
].string
) {
189 free((char *)subjectNames
[i
].string
);
194 /* key size verifier - one for each key alg */
196 static bool rsaKeySizeVerify(
208 static bool dsaKeySizeVerify(
211 return((keySize
>= 512) & (keySize
<= 2048));
214 static bool feeKeySizeVerify(
227 typedef bool (*keySizeVerifyFcn
)(unsigned keySize
);
229 /* map between algorithms, string, char selector, OID */
230 typedef struct _AlgInfo
{
234 const CSSM_OID
*oid
; // only for signatures
235 uint32 defaultKeySize
; // only for keys
236 char *keyRangeString
; // only for keys
237 const struct _AlgInfo
*sigAlgInfo
; // only for keys
238 keySizeVerifyFcn vfyFcn
; // only for keys
242 * Note: CSSM_ALGID_MD2WithRSA does not work due to an inimplemented
243 * Security Server feature. Even though CSP nad CL support this, we
244 * don't really want to provide this capability anyway - it's a known
245 * insecure digest algorithm.
247 static const AlgInfo rsaSigAlgInfo
[] =
249 { CSSM_ALGID_MD5WithRSA
, "RSA with MD5", '5', &CSSMOID_MD5WithRSA
},
250 // { CSSM_ALGID_MD2WithRSA, "RSA with MD2", '2', &CSSMOID_MD2WithRSA},
251 { CSSM_ALGID_SHA1WithRSA
, "RSA with SHA1", 's', &CSSMOID_SHA1WithRSA
},
252 { CSSM_ALGID_NONE
, NULL
, 0 }
255 static const AlgInfo feeSigAlgInfo
[] =
257 { CSSM_ALGID_FEE_MD5
, "FEE with MD5", '5', &CSSMOID_APPLE_FEE_MD5
},
258 { CSSM_ALGID_FEE_SHA1
, "FEE with SHA1", 's', &CSSMOID_APPLE_FEE_SHA1
},
259 { CSSM_ALGID_SHA1WithECDSA
, "ECDSA/SHA1", 'e', &CSSMOID_APPLE_ECDSA
},
260 { CSSM_ALGID_NONE
, NULL
, 0, NULL
}
263 static const AlgInfo dsaSigAlgInfo
[] =
265 { CSSM_ALGID_SHA1WithDSA
, "DSA with SHA1", 's', &CSSMOID_SHA1WithDSA
},
266 { CSSM_ALGID_NONE
, NULL
, 0, NULL
}
269 static const AlgInfo keyAlgInfo
[] =
271 { CSSM_ALGID_RSA
, "RSA", 'r', NULL
, 512, "512..2048",
272 rsaSigAlgInfo
, rsaKeySizeVerify
},
273 { CSSM_ALGID_DSA
, "DSA", 'd', NULL
, 512, "512..2048",
274 dsaSigAlgInfo
, dsaKeySizeVerify
},
275 { CSSM_ALGID_FEE
, "FEE", 'f', NULL
, 128, "128, 161, 192",
276 feeSigAlgInfo
, feeKeySizeVerify
},
277 { CSSM_ALGID_NONE
, NULL
, 0, NULL
}
281 /* map a char response to an element of an AlgInfo array */
282 static const AlgInfo
*algInfoForSelect(
283 const AlgInfo
*algInfo
, // NULL terminated
286 while(algInfo
->str
!= NULL
) {
287 if(algInfo
->selector
== c
) {
296 /* map a CSSM_ALGORITHM to an entry in keyAlgInfo[] */
297 static const AlgInfo
*algInfoForAlg(
300 const AlgInfo
*algInfo
= keyAlgInfo
;
301 while(algInfo
->str
!= NULL
) {
302 if(algInfo
->alg
== alg
) {
311 /* get key size and algorithm for subject key */
313 CSSM_ALGORITHMS
&keyAlg
,
314 uint32
&keySizeInBits
)
317 const AlgInfo
*keyInfo
;
318 const AlgInfo
*tempInfo
;
320 /* get a key algorithm */
321 printf("\nPlease specify parameters for the key pair you will generate.\n\n");
323 /* break when we get a valid key algorithm */
324 tempInfo
= keyAlgInfo
;
325 while(tempInfo
->str
!= NULL
) {
326 printf(" %c %s\n", tempInfo
->selector
, tempInfo
->str
);
329 getStringWithPrompt("\nSelect key algorithm by letter: ", resp
, sizeof(resp
));
330 if(resp
[0] == '\0') {
331 printf("***There is no default. Please choose a key algorithm.\n");
334 keyInfo
= algInfoForSelect(keyAlgInfo
, resp
[0]);
341 /* until we get a valid key size */
342 printf("\nValid key sizes for %s are %s; default is %u\n",
343 keyInfo
->str
, keyInfo
->keyRangeString
, (unsigned)keyInfo
->defaultKeySize
);
344 getStringWithPrompt("Enter key size in bits or CR for default: ",
346 if(resp
[0] == '\0') {
347 keySizeInBits
= keyInfo
->defaultKeySize
;
350 keySizeInBits
= atoi(resp
);
352 if(keyInfo
->vfyFcn(keySizeInBits
)) {
353 printf("\nYou have selected algorithm %s, key size %u bits.\n",
354 keyInfo
->str
, (unsigned)keySizeInBits
);
355 getStringWithPrompt("OK (y/anything)? ", resp
, sizeof(resp
));
361 printf("***%u is not a legal key size for algorithm %s.\n",
362 (unsigned)keySizeInBits
, keyInfo
->str
);
365 keyAlg
= keyInfo
->alg
;
368 /* given a signing key, obtain signing algorithm (int and oid format) */
370 const CSSM_KEY
*signingKey
,
371 CSSM_ALGORITHMS
&sigAlg
,
372 const CSSM_OID
* &sigOid
)
375 const AlgInfo
*keyInfo
;
376 const AlgInfo
*tempInfo
;
377 const AlgInfo
*sigInfoArray
;
378 const AlgInfo
*sigInfo
;
380 keyInfo
= algInfoForAlg(signingKey
->KeyHeader
.AlgorithmId
);
381 if(keyInfo
== NULL
) {
382 printf("***Signing key has unknown algorithm (%u).\n",
383 (unsigned)signingKey
->KeyHeader
.AlgorithmId
);
386 sigInfoArray
= keyInfo
->sigAlgInfo
;
387 printf("\nPlease specify the algorithm with which your certificate will be "
390 /* break when we get a valid sig algorithm */
391 tempInfo
= sigInfoArray
;
392 while(tempInfo
->str
!= NULL
) {
393 printf(" %c %s\n", tempInfo
->selector
, tempInfo
->str
);
396 getStringWithPrompt("\nSelect signature algorithm by letter: ",
398 if(resp
[0] == '\0') {
399 printf("***There is no default. Please choose a signature algorithm.\n");
402 sigInfo
= algInfoForSelect(sigInfoArray
, resp
[0]);
403 if(sigInfo
== NULL
) {
404 printf("Try again.\n");
407 printf("\nYou have selected algorithm %s.\n", sigInfo
->str
);
408 getStringWithPrompt("OK (y/anything)? ", resp
, sizeof(resp
));
413 sigAlg
= sigInfo
->alg
;
414 sigOid
= sigInfo
->oid
;
418 CU_KeyUsage
getKeyUsage(bool isRoot
)
424 /* root HAS to be capable of signing */
425 prompt
= "Enter cert/key usage (s=signing, b=signing AND encrypting): ";
428 prompt
= "Enter cert/key usage (s=signing, e=encrypting, b=both): ";
431 getStringWithPrompt(prompt
, resp
, sizeof(resp
));
434 return kKeyUseSigning
;
439 return kKeyUseEncrypting
;
441 return kKeyUseSigning
| kKeyUseEncrypting
;