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
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.
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 $ */
47 /* #define DEBUG_SHVERIFY 1 */
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
);
57 (PORT_Strncmp(&libName
[index
],
58 "."SHLIB_SUFFIX
,sizeof("."SHLIB_SUFFIX
)) == 0)) {
61 PORT_Memcpy(output
,libName
,ln_len
);
62 PORT_Memcpy(&output
[ln_len
],SGN_SUFFIX
,sizeof(SGN_SUFFIX
));
67 decodeInt(unsigned char *buf
)
69 return (buf
[3]) | (buf
[2] << 8) | (buf
[1] << 16) | (buf
[0] << 24);
73 readItem(PRFileDesc
*fd
, SECItem
*item
)
79 bytesRead
= PR_Read(fd
, buf
, 4);
83 item
->len
= decodeInt(buf
);
85 item
->data
= PORT_Alloc(item
->len
);
86 if (item
->data
== NULL
) {
90 bytesRead
= PR_Read(fd
, item
->data
, item
->len
);
91 if (bytesRead
!= item
->len
) {
92 PORT_Free(item
->data
);
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 };
111 int bytesRead
, offset
;
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
));
123 hash
.len
= sizeof(hashBuf
);
129 /* figure out the name of our check file */
130 checkName
= mkCheckFileName(shName
);
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 */
145 /* read and Verify the headerthe header */
146 bytesRead
= PR_Read(checkFD
, buf
, 12);
147 if (bytesRead
!= 12) {
150 if ((buf
[0] != NSS_SIGN_CHK_MAGIC1
) || (buf
[1] != NSS_SIGN_CHK_MAGIC2
)) {
153 if ((buf
[2] != NSS_SIGN_CHK_MAJOR_VERSION
) ||
154 (buf
[3] < NSS_SIGN_CHK_MINOR_VERSION
)) {
158 if (decodeInt(&buf
[8]) != CKK_DSA
) {
163 /* seek past any future header extensions */
164 offset
= decodeInt(&buf
[4]);
165 PR_Seek(checkFD
, offset
, PR_SEEK_SET
);
168 rv
= readItem(checkFD
,&key
.params
.prime
);
169 if (rv
!= SECSuccess
) {
172 rv
= readItem(checkFD
,&key
.params
.subPrime
);
173 if (rv
!= SECSuccess
) {
176 rv
= readItem(checkFD
,&key
.params
.base
);
177 if (rv
!= SECSuccess
) {
180 rv
= readItem(checkFD
,&key
.publicValue
);
181 if (rv
!= SECSuccess
) {
184 /* read the siganture */
185 rv
= readItem(checkFD
,&signature
);
186 if (rv
!= SECSuccess
) {
190 /* done with the check file */
194 /* open our library file */
195 shFD
= PR_Open(shName
, PR_RDONLY
, 0);
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 */
204 /* hash our library file with SHA1 */
205 hashcx
= SHA1_NewContext();
206 if (hashcx
== NULL
) {
212 while ((bytesRead
= PR_Read(shFD
, buf
, sizeof(buf
))) > 0) {
213 SHA1_Update(hashcx
, buf
, bytesRead
);
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
) {
226 #ifdef DEBUG_SHVERIFY
229 fprintf(stderr
,"File %s: %d bytes\n",shName
, count
);
230 fprintf(stderr
," hash: %d bytes\n", hash
.len
);
232 for (i
=0; i
< hash
.len
; i
+= STEP
) {
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
) {
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 */
253 if (shName
!= NULL
) {
256 if (checkName
!= NULL
) {
257 PORT_Free(checkName
);
259 if (checkFD
!= NULL
) {
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
);
288 BLAPI_VerifySelf(const char *name
)
290 /* to separate shlib to verify if name is NULL */
294 return BLAPI_SHVerify(name
, (PRFuncPtr
) decodeInt
);