mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-04 16:15:25 +00:00
341 lines
9.2 KiB
C
341 lines
9.2 KiB
C
/*
|
|
* The contents of this file are subject to the Mozilla Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is the Netscape security libraries.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Alternatively, the contents of this file may be used under the
|
|
* terms of the GNU General Public License Version 2 or later (the
|
|
* "GPL"), in which case the provisions of the GPL are applicable
|
|
* instead of those above. If you wish to allow use of your
|
|
* version of this file only under the terms of the GPL and not to
|
|
* allow others to use your version of this file under the MPL,
|
|
* indicate your decision by deleting the provisions above and
|
|
* replace them with the notice and other provisions required by
|
|
* the GPL. If you do not delete the provisions above, a recipient
|
|
* may use your version of this file under either the MPL or the
|
|
* GPL.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "secutil.h"
|
|
|
|
#if defined(XP_UNIX)
|
|
#include <unistd.h>
|
|
#include <sys/time.h>
|
|
#include <termios.h>
|
|
#endif
|
|
|
|
#include "secopt.h"
|
|
|
|
#if defined(XP_WIN)
|
|
#include <time.h>
|
|
#include <conio.h>
|
|
#endif
|
|
|
|
#if defined(__sun) && !defined(SVR4)
|
|
extern int fclose(FILE*);
|
|
extern int fprintf(FILE *, char *, ...);
|
|
extern int getopt(int, char**, char*);
|
|
extern int isatty(int);
|
|
extern char *optarg;
|
|
extern char *sys_errlist[];
|
|
#define strerror(errno) sys_errlist[errno]
|
|
#endif
|
|
|
|
#include "nspr.h"
|
|
#include "prtypes.h"
|
|
#include "prtime.h"
|
|
#include "prlong.h"
|
|
|
|
static char *progName;
|
|
|
|
static SECStatus
|
|
ListKeys(SECKEYKeyDBHandle *handle, FILE *out)
|
|
{
|
|
int rt;
|
|
|
|
rt = SECU_PrintKeyNames(handle, out);
|
|
if (rt) {
|
|
SECU_PrintError(progName, "unable to list nicknames");
|
|
return SECFailure;
|
|
}
|
|
return SECSuccess;
|
|
}
|
|
|
|
static SECStatus
|
|
DumpPublicKey(SECKEYKeyDBHandle *handle, char *nickname, FILE *out)
|
|
{
|
|
SECKEYLowPrivateKey *privKey;
|
|
SECKEYLowPublicKey *publicKey;
|
|
|
|
/* check if key actually exists */
|
|
if (SECU_CheckKeyNameExists(handle, nickname) == PR_FALSE) {
|
|
SECU_PrintError(progName, "the key \"%s\" does not exist", nickname);
|
|
return SECFailure;
|
|
}
|
|
|
|
/* Read in key */
|
|
privKey = SECU_GetPrivateKey(handle, nickname);
|
|
if (!privKey) {
|
|
return SECFailure;
|
|
}
|
|
|
|
publicKey = SECKEY_LowConvertToPublicKey(privKey);
|
|
|
|
/* Output public key (in the clear) */
|
|
switch(publicKey->keyType) {
|
|
case rsaKey:
|
|
fprintf(out, "RSA Public-Key:\n");
|
|
SECU_PrintInteger(out, &publicKey->u.rsa.modulus, "modulus", 1);
|
|
SECU_PrintInteger(out, &publicKey->u.rsa.publicExponent,
|
|
"publicExponent", 1);
|
|
break;
|
|
case dsaKey:
|
|
fprintf(out, "DSA Public-Key:\n");
|
|
SECU_PrintInteger(out, &publicKey->u.dsa.params.prime, "prime", 1);
|
|
SECU_PrintInteger(out, &publicKey->u.dsa.params.subPrime,
|
|
"subPrime", 1);
|
|
SECU_PrintInteger(out, &publicKey->u.dsa.params.base, "base", 1);
|
|
SECU_PrintInteger(out, &publicKey->u.dsa.publicValue, "publicValue", 1);
|
|
break;
|
|
default:
|
|
fprintf(out, "unknown key type\n");
|
|
break;
|
|
}
|
|
return SECSuccess;
|
|
}
|
|
|
|
static SECStatus
|
|
DumpPrivateKey(SECKEYKeyDBHandle *handle, char *nickname, FILE *out)
|
|
{
|
|
SECKEYLowPrivateKey *key;
|
|
|
|
/* check if key actually exists */
|
|
if (SECU_CheckKeyNameExists(handle, nickname) == PR_FALSE) {
|
|
SECU_PrintError(progName, "the key \"%s\" does not exist", nickname);
|
|
return SECFailure;
|
|
}
|
|
|
|
/* Read in key */
|
|
key = SECU_GetPrivateKey(handle, nickname);
|
|
if (!key) {
|
|
SECU_PrintError(progName, "error retrieving key");
|
|
return SECFailure;
|
|
}
|
|
|
|
switch(key->keyType) {
|
|
case rsaKey:
|
|
fprintf(out, "RSA Private-Key:\n");
|
|
SECU_PrintInteger(out, &key->u.rsa.modulus, "modulus", 1);
|
|
SECU_PrintInteger(out, &key->u.rsa.publicExponent, "publicExponent", 1);
|
|
SECU_PrintInteger(out, &key->u.rsa.privateExponent,
|
|
"privateExponent", 1);
|
|
SECU_PrintInteger(out, &key->u.rsa.prime1, "prime1", 1);
|
|
SECU_PrintInteger(out, &key->u.rsa.prime2, "prime2", 1);
|
|
SECU_PrintInteger(out, &key->u.rsa.exponent1, "exponent1", 1);
|
|
SECU_PrintInteger(out, &key->u.rsa.exponent2, "exponent2", 1);
|
|
SECU_PrintInteger(out, &key->u.rsa.coefficient, "coefficient", 1);
|
|
break;
|
|
case dsaKey:
|
|
fprintf(out, "DSA Private-Key:\n");
|
|
SECU_PrintInteger(out, &key->u.dsa.params.prime, "prime", 1);
|
|
SECU_PrintInteger(out, &key->u.dsa.params.subPrime, "subPrime", 1);
|
|
SECU_PrintInteger(out, &key->u.dsa.params.base, "base", 1);
|
|
SECU_PrintInteger(out, &key->u.dsa.publicValue, "publicValue", 1);
|
|
SECU_PrintInteger(out, &key->u.dsa.privateValue, "privateValue", 1);
|
|
break;
|
|
default:
|
|
fprintf(out, "unknown key type\n");
|
|
break;
|
|
}
|
|
return SECSuccess;
|
|
}
|
|
|
|
static SECStatus
|
|
ChangePassword(SECKEYKeyDBHandle *handle)
|
|
{
|
|
SECStatus rv;
|
|
|
|
/* Write out database with a new password */
|
|
rv = SECU_ChangeKeyDBPassword(handle, NULL);
|
|
if (rv) {
|
|
SECU_PrintError(progName, "unable to change key password");
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
static SECStatus
|
|
DeletePrivateKey (SECKEYKeyDBHandle *keyHandle, char *nickName)
|
|
{
|
|
SECStatus rv;
|
|
|
|
rv = SECU_DeleteKeyByName (keyHandle, nickName);
|
|
if (rv != SECSuccess)
|
|
fprintf(stderr, "%s: problem deleting private key (%s)\n",
|
|
progName, SECU_Strerror(PR_GetError()));
|
|
return (rv);
|
|
|
|
}
|
|
|
|
|
|
static void
|
|
Usage(const char *progName)
|
|
{
|
|
fprintf(stderr,
|
|
"Usage: %s -p name [-d keydir]\n", progName);
|
|
fprintf(stderr,
|
|
" %s -P name [-d keydir]\n", progName);
|
|
fprintf(stderr,
|
|
" %s -D name [-d keydir]\n", progName);
|
|
fprintf(stderr,
|
|
" %s -l [-d keydir]\n", progName);
|
|
fprintf(stderr,
|
|
" %s -c [-d keydir]\n", progName);
|
|
|
|
fprintf(stderr, "%-20s Pretty print public key info for named key\n",
|
|
"-p nickname");
|
|
fprintf(stderr, "%-20s Pretty print private key info for named key\n",
|
|
"-P nickname");
|
|
fprintf(stderr, "%-20s Delete named private key from the key database\n",
|
|
"-D nickname");
|
|
fprintf(stderr, "%-20s List the nicknames for the keys in a database\n",
|
|
"-l");
|
|
fprintf(stderr, "%-20s Change the key database password\n",
|
|
"-c");
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
|
|
"-d keydir");
|
|
|
|
exit(-1);
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
int o, changePassword, deleteKey, dumpPublicKey, dumpPrivateKey, list;
|
|
char *nickname;
|
|
SECStatus rv;
|
|
SECKEYKeyDBHandle *keyHandle;
|
|
|
|
progName = strrchr(argv[0], '/');
|
|
progName = progName ? progName+1 : argv[0];
|
|
|
|
/* Parse command line arguments */
|
|
changePassword = deleteKey = dumpPublicKey = dumpPrivateKey = list = 0;
|
|
nickname = NULL;
|
|
|
|
while ((o = getopt(argc, argv, "ADP:cd:glp:")) != -1) {
|
|
switch (o) {
|
|
case '?':
|
|
Usage(progName);
|
|
break;
|
|
|
|
case 'A':
|
|
fprintf(stderr, "%s: Can no longer add a key.", progName);
|
|
fprintf(stderr, " Use pkcs12 to import a key.\n\n");
|
|
Usage(progName);
|
|
break;
|
|
|
|
case 'D':
|
|
deleteKey = 1;
|
|
nickname = optarg;
|
|
break;
|
|
|
|
case 'P':
|
|
dumpPrivateKey = 1;
|
|
nickname = optarg;
|
|
break;
|
|
|
|
case 'c':
|
|
changePassword = 1;
|
|
break;
|
|
|
|
case 'd':
|
|
SECU_ConfigDirectory(optarg);
|
|
break;
|
|
|
|
case 'g':
|
|
fprintf(stderr, "%s: Can no longer generate a key.", progName);
|
|
fprintf(stderr, " Use certutil to generate a cert request.\n\n");
|
|
Usage(progName);
|
|
break;
|
|
|
|
case 'l':
|
|
list = 1;
|
|
break;
|
|
|
|
case 'p':
|
|
dumpPublicKey = 1;
|
|
nickname = optarg;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (dumpPublicKey+changePassword+dumpPrivateKey+list+deleteKey != 1)
|
|
Usage(progName);
|
|
|
|
if ((list || changePassword) && nickname)
|
|
Usage(progName);
|
|
|
|
if ((dumpPublicKey || dumpPrivateKey || deleteKey) && !nickname)
|
|
Usage(progName);
|
|
|
|
|
|
/* Call the libsec initialization routines */
|
|
PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
|
|
SEC_Init();
|
|
|
|
/*
|
|
* XXX Note that the following opens the key database writable.
|
|
* If dumpPublicKey or dumpPrivateKey or list, though, we only want
|
|
* to open it read-only. There needs to be a better interface
|
|
* to the initialization routines so that we can specify which way
|
|
* to open it.
|
|
*/
|
|
rv = SECU_PKCS11Init();
|
|
if (rv != SECSuccess) {
|
|
SECU_PrintError(progName, "SECU_PKCS11Init failed");
|
|
return -1;
|
|
}
|
|
|
|
keyHandle = SECKEY_GetDefaultKeyDB();
|
|
if (keyHandle == NULL) {
|
|
SECU_PrintError(progName, "could not open key database");
|
|
return -1;
|
|
}
|
|
|
|
if (dumpPublicKey) {
|
|
rv = DumpPublicKey(keyHandle, nickname, stdout);
|
|
} else
|
|
if (changePassword) {
|
|
rv = ChangePassword(keyHandle);
|
|
} else
|
|
if (dumpPrivateKey) {
|
|
rv = DumpPrivateKey(keyHandle, nickname, stdout);
|
|
} else
|
|
if (list) {
|
|
rv = ListKeys(keyHandle, stdout);
|
|
} else
|
|
if (deleteKey) {
|
|
rv = DeletePrivateKey(keyHandle, nickname);
|
|
}
|
|
|
|
|
|
return rv ? -1 : 0;
|
|
}
|