1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
38 * Test program for SDR (Secret Decoder Ring) functions.
40 * $Id: shlibsign.c,v 1.14 2005/11/15 00:34:39 julien.pierre.bugs%sun.com Exp $
61 #include <sys/param.h>
62 #include <sys/types.h>
67 usage (char *program_name
)
69 PRFileDesc
*pr_stderr
;
71 pr_stderr
= PR_STDERR
;
72 PR_fprintf (pr_stderr
, "Usage:");
73 PR_fprintf (pr_stderr
, "%s [-v] -i shared_library_name\n", program_name
);
77 mkoutput(const char *input
)
79 int in_len
= PORT_Strlen(input
);
80 char *output
= PORT_Alloc(in_len
+sizeof(SGN_SUFFIX
));
81 int index
= in_len
+ 1 - sizeof("."SHLIB_SUFFIX
);
84 (PORT_Strncmp(&input
[index
],
85 "."SHLIB_SUFFIX
,sizeof("."SHLIB_SUFFIX
)) == 0)) {
88 PORT_Memcpy(output
,input
,in_len
);
89 PORT_Memcpy(&output
[in_len
],SGN_SUFFIX
,sizeof(SGN_SUFFIX
));
95 lperror(const char *string
)
97 int errNum
= PORT_GetError();
98 const char *error
= SECU_Strerror(errNum
);
99 fprintf(stderr
,"%s: %s\n",string
, error
);
103 encodeInt(unsigned char *buf
, int val
)
105 buf
[3] = (val
>> 0) & 0xff;
106 buf
[2] = (val
>> 8) & 0xff;
107 buf
[1] = (val
>> 16) & 0xff;
108 buf
[0] = (val
>> 24) & 0xff;
113 writeItem(PRFileDesc
*fd
, SECItem
*item
, char *file
)
115 unsigned char buf
[4];
118 encodeInt(buf
,item
->len
);
119 bytesWritten
= PR_Write(fd
,buf
, 4);
120 if (bytesWritten
!= 4) {
124 bytesWritten
= PR_Write(fd
, item
->data
, item
->len
);
125 if (bytesWritten
!= item
->len
) {
134 main (int argc
, char **argv
)
136 int retval
= 1; /* 0 - test succeeded. 1 - test failed */
138 PLOptState
*optstate
;
140 const char *input_file
= NULL
; /* read encrypted data from here (or create) */
141 char *output_file
= NULL
; /* write new encrypted data here */
142 PRBool verbose
= PR_FALSE
;
143 SECKEYPrivateKey
*privk
= NULL
;
144 SECKEYPublicKey
*pubk
= NULL
;
145 PK11SlotInfo
*slot
= NULL
;
149 unsigned char file_buf
[512];
150 unsigned char hash_buf
[SHA1_LENGTH
];
151 unsigned char sign_buf
[40]; /* DSA_LENGTH */
153 PK11Context
*hashcx
= NULL
;
156 PQGParams
*pqgParams
= NULL
;
157 PQGVerify
*pqgVerify
= NULL
;
161 struct stat stat_buf
;
162 char link_buf
[MAXPATHLEN
+1];
163 char *link_file
= NULL
;
166 hash
.len
= sizeof(hash_buf
); hash
.data
= hash_buf
;
167 sign
.len
= sizeof(sign_buf
); sign
.data
= sign_buf
;
169 program_name
= PL_strrchr(argv
[0], '/');
170 program_name
= program_name
? (program_name
+ 1) : argv
[0];
172 optstate
= PL_CreateOptState (argc
, argv
, "d:i:o:v");
173 if (optstate
== NULL
) {
174 SECU_PrintError (program_name
, "PL_CreateOptState failed");
178 while (PL_GetNextOpt (optstate
) == PL_OPT_OK
) {
179 switch (optstate
->option
) {
182 short_usage (program_name
);
186 long_usage (program_name
);
191 nssDir
= optstate
->value
;
195 input_file
= optstate
->value
;
199 output_file
= PORT_Strdup(optstate
->value
);
208 if (input_file
== NULL
) {
214 * Initialize the Security libraries.
216 PK11_SetPasswordFunc(SECU_GetModulePassword
);
219 rv
= NSS_Init(nssDir
);
220 if (rv
!= SECSuccess
) {
221 rv
= NSS_NoDB_Init("");
224 rv
= NSS_NoDB_Init("");
227 if (rv
!= SECSuccess
) {
228 lperror("NSS_Init failed");
232 /* Generate a DSA Key pair */
233 slot
= PK11_GetBestSlot(CKM_DSA
,NULL
);
239 printf("Generating DSA Key Pair...."); fflush(stdout
);
240 ks
= PQG_PBITS_TO_INDEX(keySize
);
241 rv
= PK11_PQG_ParamGen(ks
,&pqgParams
, &pqgVerify
);
242 if (rv
!= SECSuccess
) {
243 lperror("Generating PQG Params");
246 privk
= PK11_GenerateKeyPair(slot
, CKM_DSA_KEY_PAIR_GEN
, pqgParams
, &pubk
,
247 PR_FALSE
, PR_TRUE
, NULL
);
249 lperror("Generating DSA Key");
255 /* open the shared library */
256 fd
= PR_OpenFile(input_file
,PR_RDONLY
,0);
262 ret
= lstat(input_file
, &stat_buf
);
267 if (S_ISLNK(stat_buf
.st_mode
)) {
268 char *dirpath
,*dirend
;
269 ret
= readlink(input_file
, link_buf
, sizeof(link_buf
) - 1);
275 link_file
= mkoutput(input_file
);
276 /* get the dirname of input_file */
277 dirpath
= PORT_Strdup(input_file
);
278 dirend
= PORT_Strrchr(dirpath
, '/');
281 ret
= chdir(dirpath
);
288 input_file
= link_buf
;
289 /* get the basename of link_file */
290 dirend
= PORT_Strrchr(link_file
, '/');
292 link_file
= dirend
+ 1;
296 if (output_file
== NULL
) {
297 output_file
= mkoutput(input_file
);
300 hashcx
= PK11_CreateDigestContext(SEC_OID_SHA1
);
301 if (hashcx
== NULL
) {
302 lperror("SHA1 Digest Create");
307 while ((bytesRead
= PR_Read(fd
,file_buf
,sizeof(file_buf
))) > 0) {
308 PK11_DigestOp(hashcx
,file_buf
,bytesRead
);
320 PK11_DigestFinal(hashcx
, hash
.data
, &hash
.len
, hash
.len
);
322 if (hash
.len
!= SHA1_LENGTH
) {
323 fprintf(stderr
, "Digest length was not correct\n");
328 rv
= PK11_Sign(privk
,&sign
,&hash
);
329 if (rv
!= SECSuccess
) {
336 fprintf(stderr
,"Library File: %s %d bytes\n",input_file
, count
);
337 fprintf(stderr
,"Check File: %s\n",output_file
);
340 fprintf(stderr
,"Link: %s\n",link_file
);
343 fprintf(stderr
," hash: %d bytes\n", hash
.len
);
345 for (i
=0; i
< hash
.len
; i
+= STEP
) {
347 for (j
=0; j
< STEP
&& (i
+j
) < hash
.len
; j
++) {
348 fprintf(stderr
," %02x", hash
.data
[i
+j
]);
350 fprintf(stderr
,"\n");
352 fprintf(stderr
," signature: %d bytes\n", sign
.len
);
353 for (i
=0; i
< sign
.len
; i
+= STEP
) {
355 for (j
=0; j
< STEP
&& (i
+j
) < sign
.len
; j
++) {
356 fprintf(stderr
," %02x", sign
.data
[i
+j
]);
358 fprintf(stderr
,"\n");
362 /* open the target signature file */
363 fd
= PR_OpenFile(output_file
,PR_WRONLY
|PR_CREATE_FILE
|PR_TRUNCATE
,0666);
365 lperror(output_file
);
370 * we write the key out in a straight binary format because very
371 * low level libraries need to read an parse this file. Ideally we should
372 * just derEncode the public key (which would be pretty simple, and be
373 * more general), but then we'd need to link the ASN.1 decoder with the
377 file_buf
[0] = NSS_SIGN_CHK_MAGIC1
;
378 file_buf
[1] = NSS_SIGN_CHK_MAGIC2
;
379 file_buf
[2] = NSS_SIGN_CHK_MAJOR_VERSION
;
380 file_buf
[3] = NSS_SIGN_CHK_MINOR_VERSION
;
381 encodeInt(&file_buf
[4],12); /* offset to data start */
382 encodeInt(&file_buf
[8],CKK_DSA
);
383 bytesWritten
= PR_Write(fd
,file_buf
, 12);
384 if (bytesWritten
!= 12) {
385 lperror(output_file
);
389 rv
= writeItem(fd
,&pubk
->u
.dsa
.params
.prime
,output_file
);
390 if (rv
!= SECSuccess
) goto loser
;
391 rv
= writeItem(fd
,&pubk
->u
.dsa
.params
.subPrime
,output_file
);
392 if (rv
!= SECSuccess
) goto loser
;
393 rv
= writeItem(fd
,&pubk
->u
.dsa
.params
.base
,output_file
);
394 if (rv
!= SECSuccess
) goto loser
;
395 rv
= writeItem(fd
,&pubk
->u
.dsa
.publicValue
,output_file
);
396 if (rv
!= SECSuccess
) goto loser
;
397 rv
= writeItem(fd
,&sign
,output_file
);
398 if (rv
!= SECSuccess
) goto loser
;
404 (void)unlink(link_file
);
405 ret
= symlink(output_file
, link_file
);
417 PK11_DestroyContext(hashcx
, PR_TRUE
);
420 SECKEY_DestroyPrivateKey(privk
);
423 SECKEY_DestroyPublicKey(pubk
);
428 if (NSS_Shutdown() != SECSuccess
) {