diff options
Diffstat (limited to 'nss/lib/freebl/shvfy.c')
-rw-r--r-- | nss/lib/freebl/shvfy.c | 324 |
1 files changed, 175 insertions, 149 deletions
diff --git a/nss/lib/freebl/shvfy.c b/nss/lib/freebl/shvfy.c index ad64a26..af4a34f 100644 --- a/nss/lib/freebl/shvfy.c +++ b/nss/lib/freebl/shvfy.c @@ -16,6 +16,7 @@ #include "prmem.h" #include "hasht.h" #include "pqg.h" +#include "blapii.h" /* * Most modern version of Linux support a speed optimization scheme where an @@ -28,7 +29,7 @@ * The modification of the shared library is correctly detected by the freebl * FIPS checksum scheme where we check a signed hash of the library against the * library itself. - * + * * The prelink command itself can reverse the process of modification and * output the prestine shared library as it was before prelink made it's * changes. If FREEBL_USE_PRELINK is set Freebl uses prelink to output the @@ -49,10 +50,10 @@ /* * This function returns an NSPR PRFileDesc * which the caller can read to * obtain the prestine value of the shared library, before any OS related - * changes to it (usually address fixups). + * changes to it (usually address fixups). * * If prelink is installed, this - * file descriptor is a pipe connecting the output of + * file descriptor is a pipe connecting the output of * /usr/sbin/prelink -u -o - {Library} * and *pid returns the process id of the prelink child. * @@ -62,115 +63,121 @@ PRFileDesc * bl_OpenUnPrelink(const char *shName, int *pid) { - char *command= strdup(FREEBL_PRELINK_COMMAND); + char *command = strdup(FREEBL_PRELINK_COMMAND); char *argString = NULL; - char **argv = NULL; + char **argv = NULL; char *shNameArg = NULL; char *cp; pid_t child; int argc = 0, argNext = 0; struct stat statBuf; - int pipefd[2] = {-1,-1}; + int pipefd[2] = { -1, -1 }; int ret; *pid = 0; /* make sure the prelink command exists first. If not, fall back to * just reading the file */ - for (cp = command; *cp ; cp++) { - if (*cp == ' ') { - *cp++ = 0; - argString = cp; - break; + for (cp = command; *cp; cp++) { + if (*cp == ' ') { + *cp++ = 0; + argString = cp; + break; } } - memset (&statBuf, 0, sizeof(statBuf)); + memset(&statBuf, 0, sizeof(statBuf)); /* stat the file, follow the link */ ret = stat(command, &statBuf); if (ret < 0) { - free(command); - return PR_Open(shName, PR_RDONLY, 0); + free(command); + return PR_Open(shName, PR_RDONLY, 0); } /* file exits, make sure it's an executable */ - if (!S_ISREG(statBuf.st_mode) || - ((statBuf.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0)) { - free(command); - return PR_Open(shName, PR_RDONLY, 0); + if (!S_ISREG(statBuf.st_mode) || + ((statBuf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0)) { + free(command); + return PR_Open(shName, PR_RDONLY, 0); } /* OK, the prelink command exists and looks correct, use it */ /* build the arglist while we can still malloc */ /* count the args if any */ if (argString && *argString) { - /* argString may have leading spaces, strip them off*/ - for (cp = argString; *cp && *cp == ' '; cp++); - argString = cp; - if (*cp) { - /* there is at least one arg.. */ - argc = 1; - } + /* argString may have leading spaces, strip them off*/ + for (cp = argString; *cp && *cp == ' '; cp++) + ; + argString = cp; + if (*cp) { + /* there is at least one arg.. */ + argc = 1; + } /* count the rest: Note there is no provision for escaped * spaces here */ - for (cp = argString; *cp ; cp++) { - if (*cp == ' ') { - while (*cp && *cp == ' ') cp++; - if (*cp) argc++; - } - } + for (cp = argString; *cp; cp++) { + if (*cp == ' ') { + while (*cp && *cp == ' ') + cp++; + if (*cp) + argc++; + } + } } /* add the additional args: argv[0] (command), shName, NULL*/ argc += 3; argv = PORT_NewArray(char *, argc); if (argv == NULL) { - goto loser; + goto loser; } /* fill in the arglist */ argv[argNext++] = command; if (argString && *argString) { - argv[argNext++] = argString; - for (cp = argString; *cp; cp++) { - if (*cp == ' ') { - *cp++ = 0; - while (*cp && *cp == ' ') cp++; - if (*cp) argv[argNext++] = cp; - } - } + argv[argNext++] = argString; + for (cp = argString; *cp; cp++) { + if (*cp == ' ') { + *cp++ = 0; + while (*cp && *cp == ' ') + cp++; + if (*cp) + argv[argNext++] = cp; + } + } } /* exec doesn't advertise taking const char **argv, do the paranoid * copy */ shNameArg = strdup(shName); if (shNameArg == NULL) { - goto loser; + goto loser; } argv[argNext++] = shNameArg; argv[argNext++] = 0; - + ret = pipe(pipefd); if (ret < 0) { - goto loser; + goto loser; } /* use vfork() so we don't trigger the pthread_at_fork() handlers */ child = vfork(); - if (child < 0) goto loser; + if (child < 0) + goto loser; if (child == 0) { - /* set up the file descriptors */ - /* if we need to support BSD, this will need to be an open of - * /dev/null and dup2(nullFD, 0)*/ - close(0); - /* associate pipefd[1] with stdout */ - if (pipefd[1] != 1) dup2(pipefd[1], 1); - close(2); - close(pipefd[0]); - /* should probably close the other file descriptors? */ - - - execv(command, argv); - /* avoid at_exit() handlers */ - _exit(1); /* shouldn't reach here except on an error */ + /* set up the file descriptors */ + /* if we need to support BSD, this will need to be an open of + * /dev/null and dup2(nullFD, 0)*/ + close(0); + /* associate pipefd[1] with stdout */ + if (pipefd[1] != 1) + dup2(pipefd[1], 1); + close(2); + close(pipefd[0]); + /* should probably close the other file descriptors? */ + + execv(command, argv); + /* avoid at_exit() handlers */ + _exit(1); /* shouldn't reach here except on an error */ } close(pipefd[1]); pipefd[1] = -1; @@ -188,10 +195,10 @@ bl_OpenUnPrelink(const char *shName, int *pid) loser: if (pipefd[0] != -1) { - close(pipefd[0]); + close(pipefd[0]); } if (pipefd[1] != -1) { - close(pipefd[1]); + close(pipefd[1]); } free(command); free(shNameArg); @@ -209,13 +216,13 @@ loser: * from hanging around. */ void -bl_CloseUnPrelink( PRFileDesc *file, int pid) +bl_CloseUnPrelink(PRFileDesc *file, int pid) { /* close the file descriptor */ PR_Close(file); /* reap the child */ if (pid) { - waitpid(pid, NULL, 0); + waitpid(pid, NULL, 0); } } #endif @@ -226,16 +233,16 @@ static char * mkCheckFileName(const char *libName) { int ln_len = PORT_Strlen(libName); - char *output = PORT_Alloc(ln_len+sizeof(SGN_SUFFIX)); - int index = ln_len + 1 - sizeof("."SHLIB_SUFFIX); + char *output = PORT_Alloc(ln_len + sizeof(SGN_SUFFIX)); + int index = ln_len + 1 - sizeof("." SHLIB_SUFFIX); if ((index > 0) && (PORT_Strncmp(&libName[index], - "."SHLIB_SUFFIX,sizeof("."SHLIB_SUFFIX)) == 0)) { + "." SHLIB_SUFFIX, sizeof("." SHLIB_SUFFIX)) == 0)) { ln_len = index; } - PORT_Memcpy(output,libName,ln_len); - PORT_Memcpy(&output[ln_len],SGN_SUFFIX,sizeof(SGN_SUFFIX)); + PORT_Memcpy(output, libName, ln_len); + PORT_Memcpy(&output[ln_len], SGN_SUFFIX, sizeof(SGN_SUFFIX)); return output; } @@ -251,55 +258,68 @@ readItem(PRFileDesc *fd, SECItem *item) unsigned char buf[4]; int bytesRead; - bytesRead = PR_Read(fd, buf, 4); if (bytesRead != 4) { - return SECFailure; + return SECFailure; } item->len = decodeInt(buf); item->data = PORT_Alloc(item->len); if (item->data == NULL) { - item->len = 0; - return SECFailure; + item->len = 0; + return SECFailure; } bytesRead = PR_Read(fd, item->data, item->len); if (bytesRead != item->len) { - PORT_Free(item->data); - item->data = NULL; - item->len = 0; - return SECFailure; + PORT_Free(item->data); + item->data = NULL; + item->len = 0; + return SECFailure; } return SECSuccess; } -PRBool -BLAPI_SHVerify(const char *name, PRFuncPtr addr) +static PRBool blapi_SHVerifyFile(const char *shName, PRBool self); + +static PRBool +blapi_SHVerify(const char *name, PRFuncPtr addr, PRBool self) { PRBool result = PR_FALSE; /* if anything goes wrong, - * the signature does not verify */ + * the signature does not verify */ /* find our shared library name */ char *shName = PR_GetLibraryFilePathname(name, addr); if (!shName) { - goto loser; + goto loser; } - result = BLAPI_SHVerifyFile(shName); + result = blapi_SHVerifyFile(shName, self); loser: if (shName != NULL) { - PR_Free(shName); + PR_Free(shName); } return result; } PRBool +BLAPI_SHVerify(const char *name, PRFuncPtr addr) +{ + return blapi_SHVerify(name, addr, PR_FALSE); +} + +PRBool BLAPI_SHVerifyFile(const char *shName) { + return blapi_SHVerifyFile(shName, PR_FALSE); +} + +static PRBool +blapi_SHVerifyFile(const char *shName, PRBool self) +{ char *checkName = NULL; PRFileDesc *checkFD = NULL; PRFileDesc *shFD = NULL; - void *hashcx = NULL; + void *hashcx = NULL; const SECHashObject *hashObj = NULL; SECItem signature = { 0, NULL, 0 }; SECItem hash; @@ -312,22 +332,28 @@ BLAPI_SHVerifyFile(const char *shName) #endif PRBool result = PR_FALSE; /* if anything goes wrong, - * the signature does not verify */ + * the signature does not verify */ unsigned char buf[4096]; unsigned char hashBuf[HASH_LENGTH_MAX]; - PORT_Memset(&key,0,sizeof(key)); + PORT_Memset(&key, 0, sizeof(key)); hash.data = hashBuf; hash.len = sizeof(hashBuf); + /* If our integrity check was never ran or failed, fail any other + * integrity checks to prevent any token going into FIPS mode. */ + if (!self && (BL_FIPSEntryOK(PR_FALSE) != SECSuccess)) { + return PR_FALSE; + } + if (!shName) { - goto loser; + goto loser; } /* figure out the name of our check file */ checkName = mkCheckFileName(shName); if (!checkName) { - goto loser; + goto loser; } /* open the check File */ @@ -337,52 +363,54 @@ BLAPI_SHVerifyFile(const char *shName) fprintf(stderr, "Failed to open the check file %s: (%d, %d)\n", checkName, (int)PR_GetError(), (int)PR_GetOSError()); #endif /* DEBUG_SHVERIFY */ - goto loser; + goto loser; } /* read and Verify the headerthe header */ bytesRead = PR_Read(checkFD, buf, 12); if (bytesRead != 12) { - goto loser; + goto loser; } if ((buf[0] != NSS_SIGN_CHK_MAGIC1) || (buf[1] != NSS_SIGN_CHK_MAGIC2)) { - goto loser; + goto loser; } - if ((buf[2] != NSS_SIGN_CHK_MAJOR_VERSION) || - (buf[3] < NSS_SIGN_CHK_MINOR_VERSION)) { - goto loser; + if ((buf[2] != NSS_SIGN_CHK_MAJOR_VERSION) || + (buf[3] < NSS_SIGN_CHK_MINOR_VERSION)) { + goto loser; } #ifdef notdef if (decodeInt(&buf[8]) != CKK_DSA) { - goto loser; + goto loser; } #endif /* seek past any future header extensions */ offset = decodeInt(&buf[4]); - PR_Seek(checkFD, offset, PR_SEEK_SET); + if (PR_Seek(checkFD, offset, PR_SEEK_SET) < 0) { + goto loser; + } /* read the key */ - rv = readItem(checkFD,&key.params.prime); + rv = readItem(checkFD, &key.params.prime); if (rv != SECSuccess) { - goto loser; + goto loser; } - rv = readItem(checkFD,&key.params.subPrime); + rv = readItem(checkFD, &key.params.subPrime); if (rv != SECSuccess) { - goto loser; + goto loser; } - rv = readItem(checkFD,&key.params.base); + rv = readItem(checkFD, &key.params.base); if (rv != SECSuccess) { - goto loser; + goto loser; } - rv = readItem(checkFD,&key.publicValue); + rv = readItem(checkFD, &key.publicValue); if (rv != SECSuccess) { - goto loser; + goto loser; } /* read the siganture */ - rv = readItem(checkFD,&signature); + rv = readItem(checkFD, &signature); if (rv != SECSuccess) { - goto loser; + goto loser; } /* done with the check file */ @@ -391,12 +419,12 @@ BLAPI_SHVerifyFile(const char *shName) hashObj = HASH_GetRawHashObject(PQG_GetHashType(&key.params)); if (hashObj == NULL) { - goto loser; + goto loser; } - /* open our library file */ +/* open our library file */ #ifdef FREEBL_USE_PRELINK - shFD = bl_OpenUnPrelink(shName,&pid); + shFD = bl_OpenUnPrelink(shName, &pid); #else shFD = PR_Open(shName, PR_RDONLY, 0); #endif @@ -405,20 +433,20 @@ BLAPI_SHVerifyFile(const char *shName) fprintf(stderr, "Failed to open the library file %s: (%d, %d)\n", shName, (int)PR_GetError(), (int)PR_GetOSError()); #endif /* DEBUG_SHVERIFY */ - goto loser; + goto loser; } /* hash our library file with SHA1 */ hashcx = hashObj->create(); if (hashcx == NULL) { - goto loser; + goto loser; } hashObj->begin(hashcx); count = 0; while ((bytesRead = PR_Read(shFD, buf, sizeof(buf))) > 0) { - hashObj->update(hashcx, buf, bytesRead); - count += bytesRead; + hashObj->update(hashcx, buf, bytesRead); + count += bytesRead; } #ifdef FREEBL_USE_PRELINK bl_CloseUnPrelink(shFD, pid); @@ -429,66 +457,64 @@ BLAPI_SHVerifyFile(const char *shName) hashObj->end(hashcx, hash.data, &hash.len, hash.len); - /* verify the hash against the check file */ if (DSA_VerifyDigest(&key, &signature, &hash) == SECSuccess) { - result = PR_TRUE; + result = PR_TRUE; } #ifdef DEBUG_SHVERIFY - { - int i,j; - fprintf(stderr,"File %s: %d bytes\n",shName, count); - fprintf(stderr," hash: %d bytes\n", hash.len); + { + int i, j; + fprintf(stderr, "File %s: %d bytes\n", shName, count); + fprintf(stderr, " hash: %d bytes\n", hash.len); #define STEP 10 - for (i=0; i < hash.len; i += STEP) { - fprintf(stderr," "); - for (j=0; j < STEP && (i+j) < hash.len; j++) { - fprintf(stderr," %02x", hash.data[i+j]); - } - fprintf(stderr,"\n"); + for (i = 0; i < hash.len; i += STEP) { + fprintf(stderr, " "); + for (j = 0; j < STEP && (i + j) < hash.len; j++) { + fprintf(stderr, " %02x", hash.data[i + j]); + } + fprintf(stderr, "\n"); } - fprintf(stderr," signature: %d bytes\n", signature.len); - for (i=0; i < signature.len; i += STEP) { - fprintf(stderr," "); - for (j=0; j < STEP && (i+j) < signature.len; j++) { - fprintf(stderr," %02x", signature.data[i+j]); - } - fprintf(stderr,"\n"); + fprintf(stderr, " signature: %d bytes\n", signature.len); + for (i = 0; i < signature.len; i += STEP) { + fprintf(stderr, " "); + for (j = 0; j < STEP && (i + j) < signature.len; j++) { + fprintf(stderr, " %02x", signature.data[i + j]); + } + fprintf(stderr, "\n"); } - fprintf(stderr,"Verified : %s\n",result?"TRUE": "FALSE"); + fprintf(stderr, "Verified : %s\n", result ? "TRUE" : "FALSE"); } #endif /* DEBUG_SHVERIFY */ - loser: if (checkName != NULL) { - PORT_Free(checkName); + PORT_Free(checkName); } if (checkFD != NULL) { - PR_Close(checkFD); + PR_Close(checkFD); } if (shFD != NULL) { - PR_Close(shFD); + PR_Close(shFD); } if (hashcx != NULL) { - if (hashObj) { - hashObj->destroy(hashcx,PR_TRUE); - } + if (hashObj) { + hashObj->destroy(hashcx, PR_TRUE); + } } if (signature.data != NULL) { - PORT_Free(signature.data); + PORT_Free(signature.data); } if (key.params.prime.data != NULL) { - PORT_Free(key.params.prime.data); + PORT_Free(key.params.prime.data); } if (key.params.subPrime.data != NULL) { - PORT_Free(key.params.subPrime.data); + PORT_Free(key.params.subPrime.data); } if (key.params.base.data != NULL) { - PORT_Free(key.params.base.data); + PORT_Free(key.params.base.data); } if (key.publicValue.data != NULL) { - PORT_Free(key.publicValue.data); + PORT_Free(key.publicValue.data); } return result; @@ -498,11 +524,11 @@ PRBool BLAPI_VerifySelf(const char *name) { if (name == NULL) { - /* - * If name is NULL, freebl is statically linked into softoken. - * softoken will call BLAPI_SHVerify next to verify itself. - */ - return PR_TRUE; + /* + * If name is NULL, freebl is statically linked into softoken. + * softoken will call BLAPI_SHVerify next to verify itself. + */ + return PR_TRUE; } - return BLAPI_SHVerify(name, (PRFuncPtr) decodeInt); + return blapi_SHVerify(name, (PRFuncPtr)decodeInt, PR_TRUE); } |