Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / lib / freebl / shvfy.c
blob62cb86d7ff192be36f9b1c3c1eefb8945a20f82c
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is the Netscape security libraries.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 2003
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
37 /* $Id: shvfy.c,v 1.10 2004/04/27 23:04:36 gerv%gerv.net Exp $ */
39 #include "shsign.h"
40 #include "prlink.h"
41 #include "prio.h"
42 #include "blapi.h"
43 #include "seccomon.h"
44 #include "stdio.h"
45 #include "prmem.h"
47 /* #define DEBUG_SHVERIFY 1 */
49 static char *
50 mkCheckFileName(const char *libName)
52 int ln_len = PORT_Strlen(libName);
53 char *output = PORT_Alloc(ln_len+sizeof(SGN_SUFFIX));
54 int index = ln_len + 1 - sizeof("."SHLIB_SUFFIX);
56 if ((index > 0) &&
57 (PORT_Strncmp(&libName[index],
58 "."SHLIB_SUFFIX,sizeof("."SHLIB_SUFFIX)) == 0)) {
59 ln_len = index;
61 PORT_Memcpy(output,libName,ln_len);
62 PORT_Memcpy(&output[ln_len],SGN_SUFFIX,sizeof(SGN_SUFFIX));
63 return output;
66 static int
67 decodeInt(unsigned char *buf)
69 return (buf[3]) | (buf[2] << 8) | (buf[1] << 16) | (buf[0] << 24);
72 static SECStatus
73 readItem(PRFileDesc *fd, SECItem *item)
75 unsigned char buf[4];
76 int bytesRead;
79 bytesRead = PR_Read(fd, buf, 4);
80 if (bytesRead != 4) {
81 return SECFailure;
83 item->len = decodeInt(buf);
85 item->data = PORT_Alloc(item->len);
86 if (item->data == NULL) {
87 item->len = 0;
88 return SECFailure;
90 bytesRead = PR_Read(fd, item->data, item->len);
91 if (bytesRead != item->len) {
92 PORT_Free(item->data);
93 item->data = NULL;
94 item->len = 0;
95 return SECFailure;
97 return SECSuccess;
100 PRBool
101 BLAPI_SHVerify(const char *name, PRFuncPtr addr)
103 /* find our shared library name */
104 char *shName = PR_GetLibraryFilePathname(name, addr);
105 char *checkName = NULL;
106 PRFileDesc *checkFD = NULL;
107 PRFileDesc *shFD = NULL;
108 SHA1Context *hashcx = NULL;
109 SECItem signature = { 0, NULL, 0 };
110 SECItem hash;
111 int bytesRead, offset;
112 SECStatus rv;
113 DSAPublicKey key;
114 int count;
116 PRBool result = PR_FALSE; /* if anything goes wrong,
117 * the signature does not verify */
118 unsigned char buf[512];
119 unsigned char hashBuf[SHA1_LENGTH];
121 PORT_Memset(&key,0,sizeof(key));
122 hash.data = hashBuf;
123 hash.len = sizeof(hashBuf);
125 if (!shName) {
126 goto loser;
129 /* figure out the name of our check file */
130 checkName = mkCheckFileName(shName);
131 if (!checkName) {
132 goto loser;
135 /* open the check File */
136 checkFD = PR_Open(checkName, PR_RDONLY, 0);
137 if (checkFD == NULL) {
138 #ifdef DEBUG_SHVERIFY
139 fprintf(stderr, "Failed to open the check file %s: (%d, %d)\n",
140 checkName, (int)PR_GetError(), (int)PR_GetOSError());
141 #endif /* DEBUG_SHVERIFY */
142 goto loser;
145 /* read and Verify the headerthe header */
146 bytesRead = PR_Read(checkFD, buf, 12);
147 if (bytesRead != 12) {
148 goto loser;
150 if ((buf[0] != NSS_SIGN_CHK_MAGIC1) || (buf[1] != NSS_SIGN_CHK_MAGIC2)) {
151 goto loser;
153 if ((buf[2] != NSS_SIGN_CHK_MAJOR_VERSION) ||
154 (buf[3] < NSS_SIGN_CHK_MINOR_VERSION)) {
155 goto loser;
157 #ifdef notdef
158 if (decodeInt(&buf[8]) != CKK_DSA) {
159 goto loser;
161 #endif
163 /* seek past any future header extensions */
164 offset = decodeInt(&buf[4]);
165 PR_Seek(checkFD, offset, PR_SEEK_SET);
167 /* read the key */
168 rv = readItem(checkFD,&key.params.prime);
169 if (rv != SECSuccess) {
170 goto loser;
172 rv = readItem(checkFD,&key.params.subPrime);
173 if (rv != SECSuccess) {
174 goto loser;
176 rv = readItem(checkFD,&key.params.base);
177 if (rv != SECSuccess) {
178 goto loser;
180 rv = readItem(checkFD,&key.publicValue);
181 if (rv != SECSuccess) {
182 goto loser;
184 /* read the siganture */
185 rv = readItem(checkFD,&signature);
186 if (rv != SECSuccess) {
187 goto loser;
190 /* done with the check file */
191 PR_Close(checkFD);
192 checkFD = NULL;
194 /* open our library file */
195 shFD = PR_Open(shName, PR_RDONLY, 0);
196 if (shFD == NULL) {
197 #ifdef DEBUG_SHVERIFY
198 fprintf(stderr, "Failed to open the library file %s: (%d, %d)\n",
199 shName, (int)PR_GetError(), (int)PR_GetOSError());
200 #endif /* DEBUG_SHVERIFY */
201 goto loser;
204 /* hash our library file with SHA1 */
205 hashcx = SHA1_NewContext();
206 if (hashcx == NULL) {
207 goto loser;
209 SHA1_Begin(hashcx);
211 count = 0;
212 while ((bytesRead = PR_Read(shFD, buf, sizeof(buf))) > 0) {
213 SHA1_Update(hashcx, buf, bytesRead);
214 count += bytesRead;
216 PR_Close(shFD);
217 shFD = NULL;
219 SHA1_End(hashcx, hash.data, &hash.len, hash.len);
222 /* verify the hash against the check file */
223 if (DSA_VerifyDigest(&key, &signature, &hash) == SECSuccess) {
224 result = PR_TRUE;
226 #ifdef DEBUG_SHVERIFY
228 int i,j;
229 fprintf(stderr,"File %s: %d bytes\n",shName, count);
230 fprintf(stderr," hash: %d bytes\n", hash.len);
231 #define STEP 10
232 for (i=0; i < hash.len; i += STEP) {
233 fprintf(stderr," ");
234 for (j=0; j < STEP && (i+j) < hash.len; j++) {
235 fprintf(stderr," %02x", hash.data[i+j]);
237 fprintf(stderr,"\n");
239 fprintf(stderr," signature: %d bytes\n", signature.len);
240 for (i=0; i < signature.len; i += STEP) {
241 fprintf(stderr," ");
242 for (j=0; j < STEP && (i+j) < signature.len; j++) {
243 fprintf(stderr," %02x", signature.data[i+j]);
245 fprintf(stderr,"\n");
247 fprintf(stderr,"Verified : %s\n",result?"TRUE": "FALSE");
249 #endif /* DEBUG_SHVERIFY */
252 loser:
253 if (shName != NULL) {
254 PR_Free(shName);
256 if (checkName != NULL) {
257 PORT_Free(checkName);
259 if (checkFD != NULL) {
260 PR_Close(checkFD);
262 if (shFD != NULL) {
263 PR_Close(shFD);
265 if (hashcx != NULL) {
266 SHA1_DestroyContext(hashcx,PR_TRUE);
268 if (signature.data != NULL) {
269 PORT_Free(signature.data);
271 if (key.params.prime.data != NULL) {
272 PORT_Free(key.params.prime.data);
274 if (key.params.subPrime.data != NULL) {
275 PORT_Free(key.params.subPrime.data);
277 if (key.params.base.data != NULL) {
278 PORT_Free(key.params.base.data);
280 if (key.publicValue.data != NULL) {
281 PORT_Free(key.publicValue.data);
284 return result;
287 PRBool
288 BLAPI_VerifySelf(const char *name)
290 /* to separate shlib to verify if name is NULL */
291 if (name == NULL) {
292 return PR_TRUE;
294 return BLAPI_SHVerify(name, (PRFuncPtr) decodeInt);