Esempio n. 1
0
NS_IMETHODIMP 
nsNSSCertificateDB::FindCertByDBKey(const char *aDBkey, nsISupports *aToken,
                                   nsIX509Cert **_cert)
{
  nsNSSShutDownPreventionLock locker;
  SECItem keyItem = {siBuffer, nsnull, 0};
  SECItem *dummy;
  CERTIssuerAndSN issuerSN;
  unsigned long moduleID,slotID;
  *_cert = nsnull; 
  if (!aDBkey || !*aDBkey)
    return NS_ERROR_INVALID_ARG;

  dummy = NSSBase64_DecodeBuffer(nsnull, &keyItem, aDBkey,
                                 (PRUint32)PL_strlen(aDBkey)); 
  if (!dummy || keyItem.len < NS_NSS_LONG*4) {
    PR_FREEIF(keyItem.data);
    return NS_ERROR_INVALID_ARG;
  }

  CERTCertificate *cert;
  // someday maybe we can speed up the search using the moduleID and slotID
  moduleID = NS_NSS_GET_LONG(keyItem.data);
  slotID = NS_NSS_GET_LONG(&keyItem.data[NS_NSS_LONG]);

  // build the issuer/SN structure
  issuerSN.serialNumber.len = NS_NSS_GET_LONG(&keyItem.data[NS_NSS_LONG*2]);
  issuerSN.derIssuer.len = NS_NSS_GET_LONG(&keyItem.data[NS_NSS_LONG*3]);
  if (issuerSN.serialNumber.len == 0 || issuerSN.derIssuer.len == 0
      || issuerSN.serialNumber.len + issuerSN.derIssuer.len
         != keyItem.len - NS_NSS_LONG*4) {
    PR_FREEIF(keyItem.data);
    return NS_ERROR_INVALID_ARG;
  }
  issuerSN.serialNumber.data= &keyItem.data[NS_NSS_LONG*4];
  issuerSN.derIssuer.data= &keyItem.data[NS_NSS_LONG*4+
                                              issuerSN.serialNumber.len];

  cert = CERT_FindCertByIssuerAndSN(CERT_GetDefaultCertDB(), &issuerSN);
  PR_FREEIF(keyItem.data);
  if (cert) {
    nsNSSCertificate *nssCert = new nsNSSCertificate(cert);
    CERT_DestroyCertificate(cert);
    if (nssCert == nsnull)
      return NS_ERROR_OUT_OF_MEMORY;
    NS_ADDREF(nssCert);
    *_cert = static_cast<nsIX509Cert*>(nssCert);
  }
  return NS_OK;
}
Esempio n. 2
0
void
doDecode(char * dataString, FILE *outFile, FILE *logFile)
{
    int        strLen = strlen(dataString + 1);
    SECItem   *decoded;

    decoded = NSSBase64_DecodeBuffer(NULL, NULL, dataString + 1, strLen);
    if ((decoded == NULL) || (decoded->len == 0)) {
	if (logFile) {
	    int err = PORT_GetError();
	    fprintf(logFile,"Base 64 decode failed on <%s>\n", dataString + 1);
	    fprintf(logFile," Error %d: %s\n", err, SECU_Strerror(err));
	}
	fputs(dataString, outFile);
	if (decoded)
	    SECITEM_FreeItem(decoded, PR_TRUE);
	return;
    }
    fprintf(outFile, "Decoded: \"%.*s\"\n", decoded->len, decoded->data);
    SECITEM_ZfreeItem(decoded, PR_TRUE);
}
Esempio n. 3
0
void check(PLArenaPool *arena, const char b64[], const char s[], const char sName[], bool url) {
  void *mark = NULL;
  SECItem *b64Item;
  mark = PORT_ArenaMark(arena);
  b64Item = SECITEM_AllocItem(arena, NULL, strlen(b64));
  if(b64Item == NULL){
    printf(">>> Couldn't allocate memore, SECITEM_AllocItem failed.\n");
  }
  strncpy(b64Item->data, b64, b64Item->len);

  SECItem b64Decoded;
  PORT_Memset(&b64Decoded, 0, sizeof(b64Decoded));
  if (url) {
#ifdef NSS_B64_URL_TEST
    if (!NSSBase64_URL_DecodeBuffer(arena, &b64Decoded,
                                    b64Item->data,
                                    b64Item->len)) {
      PORT_FreeArena(arena, 0);
      printf(">>> Couldn't b64decode, NSSBase64_DecodeBuffer failed (URL).\n");
      return;
    }
#endif
  } else {
    if (!NSSBase64_DecodeBuffer(arena, &b64Decoded,
                                b64Item->data,
                                b64Item->len)) {
      PORT_FreeArena(arena, 0);
      printf(">>> Couldn't b64decode, NSSBase64_DecodeBuffer failed.\n");
      return;
    }
  }
  if (strcmp(s,b64Decoded.data) != 0) {
    printf(">>> DECODING ERROR (%s):/\n>>> expected:\n%s\ngot:\n", sName, s);
    printf("%.*s---\n---", b64Decoded.len, b64Decoded.data);
  } else {
    printf("Successful decoded %s string\n", sName);
  }
  PORT_ArenaUnmark(arena, mark);
}
Esempio n. 4
0
void
doDecrypt(char * dataString, FILE *outFile, FILE *logFile, secuPWData *pwdata)
{
    int        strLen = strlen(dataString);
    SECItem   *decoded = NSSBase64_DecodeBuffer(NULL, NULL, dataString, strLen);
    SECStatus  rv;
    int        err;
    SECItem    result = { siBuffer, NULL, 0 };

    if ((decoded == NULL) || (decoded->len == 0)) {
	if (logFile) {
	    err = PORT_GetError();
	    fprintf(logFile,"Base 64 decode failed on <%s>\n", dataString);
	    fprintf(logFile," Error %d: %s\n", err, SECU_Strerror(err));
	}
	fputs(dataString, outFile);
	if (decoded)
	    SECITEM_FreeItem(decoded, PR_TRUE);
	return;
    }

    rv = PK11SDR_Decrypt(decoded, &result, pwdata);
    SECITEM_ZfreeItem(decoded, PR_TRUE);
    if (rv == SECSuccess) {
	/* result buffer has no extra space for a NULL */
	fprintf(outFile, "Decrypted: \"%.*s\"\n", result.len, result.data);
	SECITEM_ZfreeItem(&result, PR_FALSE);
	return;
    }
    /* Encryption failed. output raw input. */
    if (logFile) {
	err = PORT_GetError();
	fprintf(logFile,"SDR decrypt failed on <%s>\n", dataString);
	fprintf(logFile," Error %d: %s\n", err, SECU_Strerror(err));
    }
    fputs(dataString,outFile);
}
Esempio n. 5
0
int
handle_connection(
    PRFileDesc *tcp_sock,
    PRFileDesc *model_sock,
    int requestCert)
{
    PRFileDesc *ssl_sock = NULL;
    PRFileDesc *local_file_fd = NULL;
    char *pBuf; /* unused space at end of buf */
    const char *errString;
    PRStatus status;
    int bufRem;    /* unused bytes at end of buf */
    int bufDat;    /* characters received in buf */
    int newln = 0; /* # of consecutive newlns */
    int firstTime = 1;
    int reqLen;
    int rv;
    int numIOVs;
    PRSocketOptionData opt;
    PRIOVec iovs[16];
    char msgBuf[160];
    char buf[10240];
    char fileName[513];
    char *getData = NULL; /* inplace conversion */
    SECItem postData;
    PRBool isOcspRequest = PR_FALSE;
    PRBool isPost;

    postData.data = NULL;
    postData.len = 0;

    pBuf = buf;
    bufRem = sizeof buf;

    VLOG(("httpserv: handle_connection: starting"));
    opt.option = PR_SockOpt_Nonblocking;
    opt.value.non_blocking = PR_FALSE;
    PR_SetSocketOption(tcp_sock, &opt);

    VLOG(("httpserv: handle_connection: starting\n"));
    ssl_sock = tcp_sock;

    if (noDelay) {
        opt.option = PR_SockOpt_NoDelay;
        opt.value.no_delay = PR_TRUE;
        status = PR_SetSocketOption(ssl_sock, &opt);
        if (status != PR_SUCCESS) {
            errWarn("PR_SetSocketOption(PR_SockOpt_NoDelay, PR_TRUE)");
            if (ssl_sock) {
                PR_Close(ssl_sock);
            }
            return SECFailure;
        }
    }

    while (1) {
        const char *post;
        const char *foundStr = NULL;
        const char *tmp = NULL;

        newln = 0;
        reqLen = 0;

        rv = PR_Read(ssl_sock, pBuf, bufRem - 1);
        if (rv == 0 ||
            (rv < 0 && PR_END_OF_FILE_ERROR == PR_GetError())) {
            if (verbose)
                errWarn("HDX PR_Read hit EOF");
            break;
        }
        if (rv < 0) {
            errWarn("HDX PR_Read");
            goto cleanup;
        }
        /* NULL termination */
        pBuf[rv] = 0;
        if (firstTime) {
            firstTime = 0;
        }

        pBuf += rv;
        bufRem -= rv;
        bufDat = pBuf - buf;
        /* Parse the input, starting at the beginning of the buffer.
         * Stop when we detect two consecutive \n's (or \r\n's)
         * as this signifies the end of the GET or POST portion.
         * The posted data follows.
         */
        while (reqLen < bufDat && newln < 2) {
            int octet = buf[reqLen++];
            if (octet == '\n') {
                newln++;
            } else if (octet != '\r') {
                newln = 0;
            }
        }

        /* came to the end of the buffer, or second newln
         * If we didn't get an empty line (CRLFCRLF) then keep on reading.
         */
        if (newln < 2)
            continue;

        /* we're at the end of the HTTP request.
         * If the request is a POST, then there will be one more
         * line of data.
         * This parsing is a hack, but ok for SSL test purposes.
         */
        post = PORT_Strstr(buf, "POST ");
        if (!post || *post != 'P')
            break;

        postData.data = (void *)(buf + reqLen);

        tmp = "content-length: ";
        foundStr = PL_strcasestr(buf, tmp);
        if (foundStr) {
            int expectedPostLen;
            int havePostLen;

            expectedPostLen = atoi(foundStr + strlen(tmp));
            havePostLen = bufDat - reqLen;
            if (havePostLen >= expectedPostLen) {
                postData.len = expectedPostLen;
                break;
            }
        } else {
            /* use legacy hack */
            /* It's a post, so look for the next and final CR/LF. */
            while (reqLen < bufDat && newln < 3) {
                int octet = buf[reqLen++];
                if (octet == '\n') {
                    newln++;
                }
            }
            if (newln == 3)
                break;
        }
    } /* read loop */

    bufDat = pBuf - buf;
    if (bufDat)
        do { /* just close if no data */
            /* Have either (a) a complete get, (b) a complete post, (c) EOF */
            if (reqLen > 0) {
                PRBool isGetOrPost = PR_FALSE;
                unsigned skipChars = 0;
                isPost = PR_FALSE;

                if (!strncmp(buf, getCmd, sizeof getCmd - 1)) {
                    isGetOrPost = PR_TRUE;
                    skipChars = 4;
                } else if (!strncmp(buf, "POST ", 5)) {
                    isGetOrPost = PR_TRUE;
                    isPost = PR_TRUE;
                    skipChars = 5;
                }

                if (isGetOrPost) {
                    char *fnBegin = buf;
                    char *fnEnd;
                    char *fnstart = NULL;
                    PRFileInfo info;

                    fnBegin += skipChars;

                    fnEnd = strpbrk(fnBegin, " \r\n");
                    if (fnEnd) {
                        int fnLen = fnEnd - fnBegin;
                        if (fnLen < sizeof fileName) {
                            strncpy(fileName, fnBegin, fnLen);
                            fileName[fnLen] = 0; /* null terminate */
                            fnstart = fileName;
                            /* strip initial / because our root is the current directory*/
                            while (*fnstart && *fnstart == '/')
                                ++fnstart;
                        }
                    }
                    if (fnstart) {
                        if (!strncmp(fnstart, "ocsp", 4)) {
                            if (isPost) {
                                if (postData.data) {
                                    isOcspRequest = PR_TRUE;
                                }
                            } else {
                                if (!strncmp(fnstart, "ocsp/", 5)) {
                                    isOcspRequest = PR_TRUE;
                                    getData = fnstart + 5;
                                }
                            }
                        } else {
                            /* try to open the file named.
                             * If successful, then write it to the client.
                             */
                            status = PR_GetFileInfo(fnstart, &info);
                            if (status == PR_SUCCESS &&
                                info.type == PR_FILE_FILE &&
                                info.size >= 0) {
                                local_file_fd = PR_Open(fnstart, PR_RDONLY, 0);
                            }
                        }
                    }
                }
            }

            numIOVs = 0;

            iovs[numIOVs].iov_base = (char *)outHeader;
            iovs[numIOVs].iov_len = (sizeof(outHeader)) - 1;
            numIOVs++;

            if (isOcspRequest && caRevoInfos) {
                CERTOCSPRequest *request = NULL;
                PRBool failThisRequest = PR_FALSE;
                PLArenaPool *arena = NULL;

                if (ocspMethodsAllowed == ocspGetOnly && postData.len) {
                    failThisRequest = PR_TRUE;
                } else if (ocspMethodsAllowed == ocspPostOnly && getData) {
                    failThisRequest = PR_TRUE;
                } else if (ocspMethodsAllowed == ocspRandomGetFailure && getData) {
                    if (!(rand() % 2)) {
                        failThisRequest = PR_TRUE;
                    }
                }

                if (failThisRequest) {
                    PR_Write(ssl_sock, outBadRequestHeader, strlen(outBadRequestHeader));
                    break;
                }
                /* get is base64, post is binary.
                 * If we have base64, convert into the (empty) postData array.
                 */
                if (getData) {
                    if (urldecode_base64chars_inplace(getData) == SECSuccess) {
                        /* The code below can handle a NULL arena */
                        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
                        NSSBase64_DecodeBuffer(arena, &postData, getData, strlen(getData));
                    }
                }
                if (postData.len) {
                    request = CERT_DecodeOCSPRequest(&postData);
                }
                if (arena) {
                    PORT_FreeArena(arena, PR_FALSE);
                }
                if (!request || !request->tbsRequest ||
                    !request->tbsRequest->requestList ||
                    !request->tbsRequest->requestList[0]) {
                    PORT_Sprintf(msgBuf, "Cannot decode OCSP request.\r\n");

                    iovs[numIOVs].iov_base = msgBuf;
                    iovs[numIOVs].iov_len = PORT_Strlen(msgBuf);
                    numIOVs++;
                } else {
                    /* TODO: support more than one request entry */
                    CERTOCSPCertID *reqid = request->tbsRequest->requestList[0]->reqCert;
                    const caRevoInfo *revoInfo = NULL;
                    PRBool unknown = PR_FALSE;
                    PRBool revoked = PR_FALSE;
                    PRTime nextUpdate = 0;
                    PRTime revoDate = 0;
                    PRCList *caRevoIter;

                    caRevoIter = &caRevoInfos->link;
                    do {
                        CERTOCSPCertID *caid;

                        revoInfo = (caRevoInfo *)caRevoIter;
                        caid = revoInfo->id;

                        if (SECOID_CompareAlgorithmID(&reqid->hashAlgorithm,
                                                      &caid->hashAlgorithm) == SECEqual &&
                            SECITEM_CompareItem(&reqid->issuerNameHash,
                                                &caid->issuerNameHash) == SECEqual &&
                            SECITEM_CompareItem(&reqid->issuerKeyHash,
                                                &caid->issuerKeyHash) == SECEqual) {
                            break;
                        }
                        revoInfo = NULL;
                        caRevoIter = PR_NEXT_LINK(caRevoIter);
                    } while (caRevoIter != &caRevoInfos->link);

                    if (!revoInfo) {
                        unknown = PR_TRUE;
                        revoInfo = caRevoInfos;
                    } else {
                        CERTCrl *crl = &revoInfo->crl->crl;
                        CERTCrlEntry *entry = NULL;
                        DER_DecodeTimeChoice(&nextUpdate, &crl->nextUpdate);
                        if (crl->entries) {
                            int iv = 0;
                            /* assign, not compare */
                            while ((entry = crl->entries[iv++])) {
                                if (SECITEM_CompareItem(&reqid->serialNumber,
                                                        &entry->serialNumber) == SECEqual) {
                                    break;
                                }
                            }
                        }
                        if (entry) {
                            /* revoked status response */
                            revoked = PR_TRUE;
                            DER_DecodeTimeChoice(&revoDate, &entry->revocationDate);
                        } else {
                            /* else good status response */
                            if (!isPost && ocspMethodsAllowed == ocspGetUnknown) {
                                unknown = PR_TRUE;
                                nextUpdate = PR_Now() + (PRTime)60 * 60 * 24 * PR_USEC_PER_SEC; /*tomorrow*/
                                revoDate = PR_Now() - (PRTime)60 * 60 * 24 * PR_USEC_PER_SEC;   /*yesterday*/
                            }
                        }
                    }

                    {
                        PRTime now = PR_Now();
                        PLArenaPool *arena = NULL;
                        CERTOCSPSingleResponse *sr;
                        CERTOCSPSingleResponse **singleResponses;
                        SECItem *ocspResponse;

                        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);

                        if (unknown) {
                            sr = CERT_CreateOCSPSingleResponseUnknown(arena, reqid, now,
                                                                      &nextUpdate);
                        } else if (revoked) {
                            sr = CERT_CreateOCSPSingleResponseRevoked(arena, reqid, now,
                                                                      &nextUpdate, revoDate, NULL);
                        } else {
                            sr = CERT_CreateOCSPSingleResponseGood(arena, reqid, now,
                                                                   &nextUpdate);
                        }

                        /* meaning of value 2: one entry + one end marker */
                        singleResponses = PORT_ArenaNewArray(arena, CERTOCSPSingleResponse *, 2);
                        singleResponses[0] = sr;
                        singleResponses[1] = NULL;
                        ocspResponse = CERT_CreateEncodedOCSPSuccessResponse(arena,
                                                                             revoInfo->cert, ocspResponderID_byName, now,
                                                                             singleResponses, &pwdata);

                        if (!ocspResponse) {
                            PORT_Sprintf(msgBuf, "Failed to encode response\r\n");
                            iovs[numIOVs].iov_base = msgBuf;
                            iovs[numIOVs].iov_len = PORT_Strlen(msgBuf);
                            numIOVs++;
                        } else {
                            PR_Write(ssl_sock, outOcspHeader, strlen(outOcspHeader));
                            PR_Write(ssl_sock, ocspResponse->data, ocspResponse->len);
                            PORT_FreeArena(arena, PR_FALSE);
                        }
                    }
                    CERT_DestroyOCSPRequest(request);
                    break;
                }
            } else if (local_file_fd) {
                PRInt32 bytes;
                int errLen;
                bytes = PR_TransmitFile(ssl_sock, local_file_fd, outHeader,
                                        sizeof outHeader - 1,
                                        PR_TRANSMITFILE_KEEP_OPEN,
                                        PR_INTERVAL_NO_TIMEOUT);
                if (bytes >= 0) {
                    bytes -= sizeof outHeader - 1;
                    FPRINTF(stderr,
                            "httpserv: PR_TransmitFile wrote %d bytes from %s\n",
                            bytes, fileName);
                    break;
                }
                errString = errWarn("PR_TransmitFile");
                errLen = PORT_Strlen(errString);
                errLen = PR_MIN(errLen, sizeof msgBuf - 1);
                PORT_Memcpy(msgBuf, errString, errLen);
                msgBuf[errLen] = 0;

                iovs[numIOVs].iov_base = msgBuf;
                iovs[numIOVs].iov_len = PORT_Strlen(msgBuf);
                numIOVs++;
            } else if (reqLen <= 0) { /* hit eof */
                PORT_Sprintf(msgBuf, "Get or Post incomplete after %d bytes.\r\n",
                             bufDat);

                iovs[numIOVs].iov_base = msgBuf;
                iovs[numIOVs].iov_len = PORT_Strlen(msgBuf);
                numIOVs++;
            } else if (reqLen < bufDat) {
                PORT_Sprintf(msgBuf, "Discarded %d characters.\r\n",
                             bufDat - reqLen);

                iovs[numIOVs].iov_base = msgBuf;
                iovs[numIOVs].iov_len = PORT_Strlen(msgBuf);
                numIOVs++;
            }

            if (reqLen > 0) {
                if (verbose > 1)
                    fwrite(buf, 1, reqLen, stdout); /* display it */

                iovs[numIOVs].iov_base = buf;
                iovs[numIOVs].iov_len = reqLen;
                numIOVs++;
            }

            rv = PR_Writev(ssl_sock, iovs, numIOVs, PR_INTERVAL_NO_TIMEOUT);
            if (rv < 0) {
                errWarn("PR_Writev");
                break;
            }

        } while (0);
Esempio n. 6
0
int
main (int argc, char **argv)
{
    int		 retval = 0;  /* 0 - test succeeded.  -1 - test failed */
    SECStatus	 rv;
    PLOptState	*optstate;
    char	*program_name;
    char  *input_file = NULL; 	/* read encrypted data from here (or create) */
    char  *output_file = NULL;	/* write new encrypted data here */
    char  *log_file = NULL;	/* write new encrypted data here */
    FILE	*inFile = stdin;
    FILE	*outFile = stdout;
    FILE	*logFile = NULL;
    PLOptStatus optstatus;
    SECItem	result;
    int		c;
    secuPWData  pwdata = { PW_NONE, NULL };

    result.data = 0;

    program_name = PL_strrchr(argv[0], '/');
    program_name = program_name ? (program_name + 1) : argv[0];

    optstate = PL_CreateOptState (argc, argv, "Hd:f:i:o:l:p:?");
    if (optstate == NULL) {
        SECU_PrintError (program_name, "PL_CreateOptState failed");
        return 1;
    }

    while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
        switch (optstate->option) {
        case '?':
            short_usage (program_name);
            return 1;

        case 'H':
            long_usage (program_name);
            return 1;

        case 'd':
            SECU_ConfigDirectory(optstate->value);
            break;

        case 'i':
            input_file = PL_strdup(optstate->value);
            break;

        case 'o':
            output_file = PL_strdup(optstate->value);
            break;

        case 'l':
            log_file = PL_strdup(optstate->value);
            break;

        case 'f':
            pwdata.source = PW_FROMFILE;
            pwdata.data = PL_strdup(optstate->value);
            break;

        case 'p':
            pwdata.source = PW_PLAINTEXT;
            pwdata.data = PL_strdup(optstate->value);
            break;

        }
    }
    PL_DestroyOptState(optstate);
    if (optstatus == PL_OPT_BAD) {
        short_usage (program_name);
        return 1;
    }

    if (input_file) {
        inFile = fopen(input_file,"r");
        if (inFile == NULL) {
            perror(input_file);
            return 1;
        }
        PR_Free(input_file);
    }
    if (output_file) {
        outFile = fopen(output_file,"w+");
        if (outFile == NULL) {
            perror(output_file);
            return 1;
        }
        PR_Free(output_file);
    }
    if (log_file) {
        logFile = fopen(log_file,"w+");
        if (logFile == NULL) {
            perror(log_file);
            return 1;
        }
        PR_Free(log_file);
    }

    /*
     * Initialize the Security libraries.
     */
    PK11_SetPasswordFunc(SECU_GetModulePassword);
    rv = NSS_Init(SECU_ConfigDirectory(NULL));
    if (rv != SECSuccess) {
        SECU_PrintError (program_name, "NSS_Init failed");
        retval = 1;
        goto prdone;
    }

    /* Get the encrypted result, either from the input file
     * or from encrypting the plaintext value
     */

    while ((c = getc(inFile)) != EOF) {
        if (c == 'M') {
            char *dataString = NULL;
            SECItem *inText;

            rv = getData(inFile, &dataString);
            if (!rv) {
                fputs(dataString,outFile);
                free(dataString);
                continue;
            }
            inText = NSSBase64_DecodeBuffer(NULL, NULL, dataString,
                                            strlen(dataString));
            if ((inText == NULL) || (inText->len == 0)) {
                if (logFile) {
                    fprintf(logFile,"Base 64 decode failed on <%s>\n",
                            dataString);
                    fprintf(logFile," Error %x: %s\n",PORT_GetError(),
                            SECU_Strerror(PORT_GetError()));
                }
                fputs(dataString,outFile);
                free(dataString);
                continue;
            }
            result.data = NULL;
            result.len  = 0;
            rv = PK11SDR_Decrypt(inText, &result, &pwdata);
            SECITEM_FreeItem(inText, PR_TRUE);
            if (rv != SECSuccess) {
                if (logFile) {
                    fprintf(logFile,"SDR decrypt failed on <%s>\n",
                            dataString);
                    fprintf(logFile," Error %x: %s\n",PORT_GetError(),
                            SECU_Strerror(PORT_GetError()));
                }
                fputs(dataString,outFile);
                free(dataString);
                SECITEM_ZfreeItem(&result, PR_FALSE);
                continue;
            }
            /* result buffer has no extra space for a NULL */
            fprintf(outFile, "%.*s", result.len, result.data);
            SECITEM_ZfreeItem(&result, PR_FALSE);
        } else {
            putc(c,outFile);
        }
    }

    fclose(outFile);
    fclose(inFile);
    if (logFile) {
        fclose(logFile);
    }

    if (NSS_Shutdown() != SECSuccess) {
        SECU_PrintError (program_name, "NSS_Shutdown failed");
        exit(1);
    }

prdone:
    PR_Cleanup ();
    return retval;
}
NS_IMETHODIMP
nsDataSignatureVerifier::VerifyData(const nsACString & aData,
                                    const nsACString & aSignature,
                                    const nsACString & aPublicKey,
                                    bool *_retval)
{
    // Allocate an arena to handle the majority of the allocations
    PRArenaPool *arena;
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (!arena)
        return NS_ERROR_OUT_OF_MEMORY;

    // Base 64 decode the key
    SECItem keyItem;
    PORT_Memset(&keyItem, 0, sizeof(SECItem));
    if (!NSSBase64_DecodeBuffer(arena, &keyItem,
                                nsPromiseFlatCString(aPublicKey).get(),
                                aPublicKey.Length())) {
        PORT_FreeArena(arena, false);
        return NS_ERROR_FAILURE;
    }
    
    // Extract the public key from the data
    CERTSubjectPublicKeyInfo *pki = SECKEY_DecodeDERSubjectPublicKeyInfo(&keyItem);
    if (!pki) {
        PORT_FreeArena(arena, false);
        return NS_ERROR_FAILURE;
    }
    SECKEYPublicKey *publicKey = SECKEY_ExtractPublicKey(pki);
    SECKEY_DestroySubjectPublicKeyInfo(pki);
    pki = nullptr;
    
    if (!publicKey) {
        PORT_FreeArena(arena, false);
        return NS_ERROR_FAILURE;
    }
    
    // Base 64 decode the signature
    SECItem signatureItem;
    PORT_Memset(&signatureItem, 0, sizeof(SECItem));
    if (!NSSBase64_DecodeBuffer(arena, &signatureItem,
                                nsPromiseFlatCString(aSignature).get(),
                                aSignature.Length())) {
        SECKEY_DestroyPublicKey(publicKey);
        PORT_FreeArena(arena, false);
        return NS_ERROR_FAILURE;
    }
    
    // Decode the signature and algorithm
    CERTSignedData sigData;
    PORT_Memset(&sigData, 0, sizeof(CERTSignedData));
    SECStatus ss = SEC_QuickDERDecodeItem(arena, &sigData, 
                                          CERT_SignatureDataTemplate,
                                          &signatureItem);
    if (ss != SECSuccess) {
        SECKEY_DestroyPublicKey(publicKey);
        PORT_FreeArena(arena, false);
        return NS_ERROR_FAILURE;
    }
    
    // Perform the final verification
    DER_ConvertBitString(&(sigData.signature));
    ss = VFY_VerifyDataWithAlgorithmID((const unsigned char*)nsPromiseFlatCString(aData).get(),
                                       aData.Length(), publicKey,
                                       &(sigData.signature),
                                       &(sigData.signatureAlgorithm),
                                       NULL, NULL);
    
    // Clean up remaining objects
    SECKEY_DestroyPublicKey(publicKey);
    PORT_FreeArena(arena, false);
    
    *_retval = (ss == SECSuccess);

    return NS_OK;
}
Esempio n. 8
0
int
main (int argc, char **argv)
{
    int		 retval = 0;  /* 0 - test succeeded.  -1 - test failed */
    SECStatus	 rv;
    PLOptState	*optstate;
    PLOptStatus  optstatus;
    char	*program_name;
    const char  *input_file = NULL; 	/* read encrypted data from here (or create) */
    const char  *output_file = NULL;	/* write new encrypted data here */
    const char  *value = default_value;	/* Use this for plaintext */
    SECItem     data;
    SECItem     result = {0, 0, 0};
    SECItem     text;
    PRBool      ascii = PR_FALSE;
    secuPWData  pwdata = { PW_NONE, 0 };

    pr_stderr = PR_STDERR;
    result.data = 0;
    text.data = 0; text.len = 0;

    program_name = PL_strrchr(argv[0], '/');
    program_name = program_name ? (program_name + 1) : argv[0];

    optstate = PL_CreateOptState (argc, argv, "?Had:i:o:t:vf:p:");
    if (optstate == NULL) {
	SECU_PrintError (program_name, "PL_CreateOptState failed");
	return -1;
    }

    while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
	switch (optstate->option) {
	  case '?':
	    short_usage (program_name);
	    return retval;

	  case 'H':
	    long_usage (program_name);
	    return retval;

	  case 'a':
	    ascii = PR_TRUE;
	    break;

	  case 'd':
	    SECU_ConfigDirectory(optstate->value);
	    break;

          case 'i':
            input_file = optstate->value;
            break;

          case 'o':
            output_file = optstate->value;
            break;

          case 't':
            value = optstate->value;
            break;

	  case 'f':
	    if (pwdata.data) {
		PORT_Free(pwdata.data);
		short_usage(program_name);
		return -1;
	    }
	    pwdata.source = PW_FROMFILE;
	    pwdata.data = PORT_Strdup(optstate->value);
	    break;

	  case 'p':
	    if (pwdata.data) {
		PORT_Free(pwdata.data);
		short_usage(program_name);
		return -1;
	    }
	    pwdata.source = PW_PLAINTEXT;
	    pwdata.data = PORT_Strdup(optstate->value);
	    break;

          case 'v':
            verbose = PR_TRUE;
            break;
	}
    }
    PL_DestroyOptState(optstate);
    if (optstatus == PL_OPT_BAD) {
	short_usage (program_name);
	return -1;
    }
    if (!output_file && !input_file && value == default_value) {
	short_usage (program_name);
	PR_fprintf (pr_stderr, "Must specify at least one of -t, -i or -o \n");
	return -1;
    }

    /*
     * Initialize the Security libraries.
     */
    PK11_SetPasswordFunc(SECU_GetModulePassword);

    if (output_file) {
	rv = NSS_InitReadWrite(SECU_ConfigDirectory(NULL));
    } else {
	rv = NSS_Init(SECU_ConfigDirectory(NULL));
    }
    if (rv != SECSuccess) {
	SECU_PrintError(program_name, "NSS_Init failed");
	retval = -1;
	goto prdone;
    }

    /* Convert value into an item */
    data.data = (unsigned char *)value;
    data.len = strlen(value);

    /* Get the encrypted result, either from the input file
     * or from encrypting the plaintext value
     */
    if (input_file)
    {
      if (verbose) printf("Reading data from %s\n", input_file);

      if (!strcmp(input_file, "-")) {
	retval = readStdin(&result);
        ascii = PR_TRUE;
      } else {
        retval = readInputFile(input_file, &result);
      }
      if (retval != 0) 
	goto loser;
      if (ascii) {
	/* input was base64 encoded.  Decode it. */
	SECItem newResult = {0, 0, 0};
	SECItem *ok = NSSBase64_DecodeBuffer(NULL, &newResult, 
	                       (const char *)result.data, result.len);
	if (!ok) {
	  SECU_PrintError(program_name, "Base 64 decode failed");
	  retval = -1;
	  goto loser;
	}
	SECITEM_ZfreeItem(&result, PR_FALSE);
	result = *ok;
      }
    }
    else
    {
      SECItem keyid = { 0, 0, 0 };
      SECItem outBuf = { 0, 0, 0 };
      PK11SlotInfo *slot = NULL;

      /* sigh, initialize the key database */
      slot = PK11_GetInternalKeySlot();
      if (slot && PK11_NeedUserInit(slot)) {
	switch (pwdata.source) {
	case PW_FROMFILE:
	    rv = SECU_ChangePW(slot, 0, pwdata.data);
	    break;
	case PW_PLAINTEXT:
	    rv = SECU_ChangePW(slot, pwdata.data, 0);
	    break;
	default:
            rv = SECU_ChangePW(slot, "", 0);
	    break;
	}
        if (rv != SECSuccess) {
            SECU_PrintError(program_name, "Failed to initialize slot \"%s\"",
                                    PK11_GetSlotName(slot));
            return SECFailure;
        }
      }
      if (slot) {
	PK11_FreeSlot(slot);
      }

      rv = PK11SDR_Encrypt(&keyid, &data, &result, &pwdata);
      if (rv != SECSuccess) {
        if (verbose) 
	  SECU_PrintError(program_name, "Encrypt operation failed\n");
        retval = -1;
        goto loser;
      }

      if (verbose) printf("Encrypted result is %d bytes long\n", result.len);

      if (!strcmp(output_file, "-")) {
        ascii = PR_TRUE;
      }

      if (ascii) {
      	/* base64 encode output. */
	char * newResult = NSSBase64_EncodeItem(NULL, NULL, 0, &result);
	if (!newResult) {
	  SECU_PrintError(program_name, "Base 64 encode failed\n");
	  retval = -1;
	  goto loser;
	}
	outBuf.data = (unsigned char *)newResult;
	outBuf.len  = strlen(newResult);
	if (verbose) 
	  printf("Base 64 encoded result is %d bytes long\n", outBuf.len);
      } else {
	outBuf = result;
      }

      /* -v printf("Result is %.*s\n", text.len, text.data); */
      if (output_file) {
         PRFileDesc *file;
         PRInt32 count;

         if (verbose) printf("Writing result to %s\n", output_file);
	 if (!strcmp(output_file, "-")) {
	   file = PR_STDOUT;
	 } else {
	   /* Write to file */
	   file = PR_Open(output_file, PR_CREATE_FILE|PR_WRONLY, 0666);
	 }
         if (!file) {
            if (verbose) 
		SECU_PrintError(program_name, 
                                "Open of output file %s failed\n",
                                output_file);
            retval = -1;
            goto loser;
         }

         count = PR_Write(file, outBuf.data, outBuf.len);

	 if (file == PR_STDOUT) {
	   puts("");
	 } else {
	   PR_Close(file);
	 }

         if (count != outBuf.len) {
           if (verbose) SECU_PrintError(program_name, "Write failed\n");
           retval = -1;
           goto loser;
         }
	 if (ascii) {
	   free(outBuf.data);
	 }
      }
    }

    /* Decrypt the value */
    rv = PK11SDR_Decrypt(&result, &text, &pwdata);
    if (rv != SECSuccess) {
      if (verbose) SECU_PrintError(program_name, "Decrypt operation failed\n");
      retval = -1; 
      goto loser;
    }

    if (verbose) printf("Decrypted result is \"%.*s\"\n", text.len, text.data);

    /* Compare to required value */
    if (text.len != data.len || memcmp(data.data, text.data, text.len) != 0)
    {
      if (verbose) PR_fprintf(pr_stderr, "Comparison failed\n");
      retval = -1;
      goto loser;
    }

loser:
    if (text.data) SECITEM_ZfreeItem(&text, PR_FALSE);
    if (result.data) SECITEM_ZfreeItem(&result, PR_FALSE);
    if (NSS_Shutdown() != SECSuccess) {
       exit(1);
    }

prdone:
    PR_Cleanup ();
    if (pwdata.data) {
	PORT_Free(pwdata.data);
    }
    return retval;
}