示例#1
0
文件: actions.c 项目: fpmurphy/pesign
static void
parse_signature(pesign_context *ctx, uint8_t **data, unsigned int *datalen)
{
	int rc;
	char *sig;
	size_t siglen;

	rc = read_file(ctx->insigfd, &sig, &siglen);
	if (rc < 0) {
		fprintf(stderr, "pesign: could not read signature.\n");
		exit(1);
	}
	close(ctx->insigfd);
	ctx->insigfd = -1;

	unsigned char *der;
	unsigned int derlen;
	

	/* XXX FIXME: ignoring length for now */
	char *base64 = strstr(sig, sig_begin_marker);
	if (base64) {
		base64 += strlen(sig_begin_marker);
		char *end = strstr(base64, sig_end_marker);
		if (!end) {
			fprintf(stderr, "pesign: Invalid signature.\n");
			exit(1);
		}
	
		derlen = end - base64;
		base64[derlen] = '\0';

		der = ATOB_AsciiToData(base64, &derlen);
	} else {
		der = PORT_Alloc(siglen);
		memmove(der, sig, siglen);
		derlen = siglen;
	}
	free(sig);

	*data = der;
	*datalen = derlen;

#if 0
	SEC_PKCS7DecoderContext *dc = NULL;
	saw_content = 0;
	dc = SEC_PKCS7DecoderStart(handle_bytes, NULL, NULL, NULL, NULL, NULL,
				decryption_allowed);
	if (dc == NULL) {
decoder_error:
		fprintf(stderr, "pesign: Invalid signature.\n");
		PORT_Free(der);
		exit(1);
	}

	SECStatus status = SEC_PKCS7DecoderUpdate(dc, (char *)der, derlen);
	if (status != SECSuccess)
		goto decoder_error;

	SEC_PKCS7ContentInfo *cinfo = SEC_PKCS7DecoderFinish(dc);
	if (!cinfo)
		goto decoder_error;

	ctx->cinfo = cinfo;
	PORT_Free(der);
#endif
}
示例#2
0
/*
 *  J A R _ g e t _ e r r o r
 *
 *  This is provided to map internal JAR errors to strings for
 *  the Java console. Also, a DLL may call this function if it does
 *  not have access to the XP_GetString function.
 *
 *  These strings aren't UI, since they are Java console only.
 *
 */
char *
JAR_get_error(int status)
{
    char *errstring = NULL;

    switch (status) {
    case JAR_ERR_GENERAL:
	errstring = "General JAR file error";
	break;

    case JAR_ERR_FNF:
	errstring = "JAR file not found";
	break;

    case JAR_ERR_CORRUPT:
	errstring = "Corrupt JAR file";
	break;

    case JAR_ERR_MEMORY:
	errstring = "Out of memory";
	break;

    case JAR_ERR_DISK:
	errstring = "Disk error (perhaps out of space)";
	break;

    case JAR_ERR_ORDER:
	errstring = "Inconsistent files in META-INF directory";
	break;

    case JAR_ERR_SIG:
	errstring = "Invalid digital signature file";
	break;

    case JAR_ERR_METADATA:
	errstring = "JAR metadata failed verification";
	break;

    case JAR_ERR_ENTRY:
	errstring = "No Manifest entry for this JAR entry";
	break;

    case JAR_ERR_HASH:
	errstring = "Invalid Hash of this JAR entry";
	break;

    case JAR_ERR_PK7:
	errstring = "Strange PKCS7 or RSA failure";
	break;

    case JAR_ERR_PNF:
	errstring = "Path not found inside JAR file";
	break;

    default:
	if (jar_fn_GetString) {
	    errstring = jar_fn_GetString (status);
	} else {
	    /* this is not a normal situation, and would only be
	       called in cases of improper initialization */
	    char *err = (char*)PORT_Alloc (40);
	    if (err)
		PR_snprintf (err, 39,  "Error %d\n", status); /* leak me! */
	    else
		err = "Error! Bad! Out of memory!";
	    return err;
	}
	break;
    }
    return errstring;
}
示例#3
0
/*
 * read an old style ascii or binary certificate chain
 */
SECStatus
CERT_DecodeCertPackage(char *certbuf,
		       int certlen,
		       CERTImportCertificateFunc f,
		       void *arg)
{
    unsigned char *cp;
    unsigned char *bincert = NULL;
    char *         ascCert = NULL;
    SECStatus      rv;
    
    if ( certbuf == NULL ) {
	return(SECFailure);
    }
    
    cp = (unsigned char *)certbuf;

    /* is a DER encoded certificate of some type? */
    if ( ( *cp  & 0x1f ) == SEC_ASN1_SEQUENCE ) {
	SECItem certitem;
	SECItem *pcertitem = &certitem;
	int seqLen, seqLenLen;

	cp++;
	
	if ( *cp & 0x80) {
	    /* Multibyte length */
	    seqLenLen = cp[0] & 0x7f;
	    
	    switch (seqLenLen) {
	      case 4:
		seqLen = ((unsigned long)cp[1]<<24) |
		    ((unsigned long)cp[2]<<16) | (cp[3]<<8) | cp[4];
		break;
	      case 3:
		seqLen = ((unsigned long)cp[1]<<16) | (cp[2]<<8) | cp[3];
		break;
	      case 2:
		seqLen = (cp[1]<<8) | cp[2];
		break;
	      case 1:
		seqLen = cp[1];
		break;
	      default:
		/* indefinite length */
		seqLen = 0;
	    }
	    cp += ( seqLenLen + 1 );

	} else {
	    seqLenLen = 0;
	    seqLen = *cp;
	    cp++;
	}

	/* check entire length if definite length */
	if ( seqLen || seqLenLen ) {
	    if ( certlen != ( seqLen + seqLenLen + 2 ) ) {
		if (certlen > ( seqLen + seqLenLen + 2 ))
		    PORT_SetError(SEC_ERROR_EXTRA_INPUT);
		else 
		    PORT_SetError(SEC_ERROR_INPUT_LEN);
		goto notder;
	    }
	}
	
	/* check the type string */
	/* netscape wrapped DER cert */
	if ( ( cp[0] == SEC_ASN1_OCTET_STRING ) &&
	    ( cp[1] == CERTIFICATE_TYPE_LEN ) &&
	    ( PORT_Strcmp((char *)&cp[2], CERTIFICATE_TYPE_STRING) ) ) {
	    
	    cp += ( CERTIFICATE_TYPE_LEN + 2 );

	    /* it had better be a certificate by now!! */
	    certitem.data = cp;
	    certitem.len = certlen - ( cp - (unsigned char *)certbuf );
	    
	    rv = (* f)(arg, &pcertitem, 1);
	    
	    return(rv);
	} else if ( cp[0] == SEC_ASN1_OBJECT_ID ) {
	    SECOidData *oiddata;
	    SECItem oiditem;
	    /* XXX - assume DER encoding of OID len!! */
	    oiditem.len = cp[1];
	    oiditem.data = (unsigned char *)&cp[2];
	    oiddata = SECOID_FindOID(&oiditem);
	    if ( oiddata == NULL ) {
		return(SECFailure);
	    }

	    certitem.data = (unsigned char*)certbuf;
	    certitem.len = certlen;
	    
	    switch ( oiddata->offset ) {
	      case SEC_OID_PKCS7_SIGNED_DATA:
		return(SEC_ReadPKCS7Certs(&certitem, f, arg));
		break;
	      case SEC_OID_NS_TYPE_CERT_SEQUENCE:
		return(SEC_ReadCertSequence(&certitem, f, arg));
		break;
	      default:
		break;
	    }
	    
	} else {
	    /* it had better be a certificate by now!! */
	    certitem.data = (unsigned char*)certbuf;
	    certitem.len = certlen;
	    
	    rv = (* f)(arg, &pcertitem, 1);
	    return(rv);
	}
    }

    /* now look for a netscape base64 ascii encoded cert */
notder:
  {
    unsigned char *certbegin = NULL; 
    unsigned char *certend   = NULL;
    char          *pc;
    int cl;

    /* Convert the ASCII data into a nul-terminated string */
    ascCert = (char *)PORT_Alloc(certlen + 1);
    if (!ascCert) {
        rv = SECFailure;
	goto loser;
    }

    PORT_Memcpy(ascCert, certbuf, certlen);
    ascCert[certlen] = '\0';

    pc = PORT_Strchr(ascCert, '\n');  /* find an EOL */
    if (!pc) { /* maybe this is a MAC file */
	pc = ascCert;
	while (*pc && NULL != (pc = PORT_Strchr(pc, '\r'))) {
	    *pc++ = '\n';
	}
    }

    cp = (unsigned char *)ascCert;
    cl = certlen;

    /* find the beginning marker */
    while ( cl > NS_CERT_HEADER_LEN ) {
	if ( !PORT_Strncasecmp((char *)cp, NS_CERT_HEADER,
			        NS_CERT_HEADER_LEN) ) {
	    cl -= NS_CERT_HEADER_LEN;
	    cp += NS_CERT_HEADER_LEN;
	    certbegin = cp;
	    break;
	}
	
	/* skip to next eol */
	do {
	    cp++;
	    cl--;
	} while ( ( *cp != '\n') && cl );

	/* skip all blank lines */
	while ( ( *cp == '\n') && cl ) {
	    cp++;
	    cl--;
	}
    }

    if ( certbegin ) {
	/* find the ending marker */
	while ( cl > NS_CERT_TRAILER_LEN ) {
	    if ( !PORT_Strncasecmp((char *)cp, NS_CERT_TRAILER,
				   NS_CERT_TRAILER_LEN) ) {
		certend = (unsigned char *)cp;
		break;
	    }

	    /* skip to next eol */
	    do {
		cp++;
		cl--;
	    } while ( ( *cp != '\n') && cl );

	    /* skip all blank lines */
	    while ( ( *cp == '\n') && cl ) {
		cp++;
		cl--;
	    }
	}
    }

    if ( certbegin && certend ) {
	unsigned int binLen;

	*certend = 0;
	/* convert to binary */
	bincert = ATOB_AsciiToData(certbegin, &binLen);
	if (!bincert) {
	    rv = SECFailure;
	    goto loser;
	}

	/* now recurse to decode the binary */
	rv = CERT_DecodeCertPackage((char *)bincert, binLen, f, arg);
	
    } else {
	rv = SECFailure;
    }
  }

loser:

    if ( bincert ) {
	PORT_Free(bincert);
    }

    if ( ascCert ) {
	PORT_Free(ascCert);
    }

    return(rv);
}
示例#4
0
nsresult
nsNSSCertificateDB::ImportValidCACertsInList(CERTCertList *certList, nsIInterfaceRequestor *ctx)
{
  SECItem **rawArray;

  /* filter out the certs we don't want */
  SECStatus srv = CERT_FilterCertListByUsage(certList, certUsageAnyCA, PR_TRUE);
  if (srv != SECSuccess) {
    return NS_ERROR_FAILURE;
  }

  /* go down the remaining list of certs and verify that they have
   * valid chains, if yes, then import.
   */
  PRTime now = PR_Now();
  CERTCertListNode *node;
  for (node = CERT_LIST_HEAD(certList);
       !CERT_LIST_END(node,certList);
       node = CERT_LIST_NEXT(node)) {

    bool alert_and_skip = false;

    if (CERT_VerifyCert(CERT_GetDefaultCertDB(), node->cert, 
        PR_TRUE, certUsageVerifyCA, now, ctx, NULL) != SECSuccess) {
      alert_and_skip = true;
    }

    CERTCertificateList *certChain = nsnull;
    CERTCertificateListCleaner chainCleaner(certChain);

    if (!alert_and_skip) {    
      certChain = CERT_CertChainFromCert(node->cert, certUsageAnyCA, PR_FALSE);
      if (!certChain) {
        alert_and_skip = true;
      }
    }

    if (alert_and_skip) {    
      nsCOMPtr<nsIX509Cert> certToShow = new nsNSSCertificate(node->cert);
      DisplayCertificateAlert(ctx, "NotImportingUnverifiedCert", certToShow);
      continue;
    }

    /*
     * CertChain returns an array of SECItems, import expects an array of
     * SECItem pointers. Create the SECItem Pointers from the array of
     * SECItems.
     */
    rawArray = (SECItem **) PORT_Alloc(certChain->len * sizeof(SECItem *));
    if (!rawArray) {
      continue;
    }
    for (int i=0; i < certChain->len; i++) {
      rawArray[i] = &certChain->certs[i];
    }
    CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageAnyCA, certChain->len, 
                            rawArray,  NULL, PR_TRUE, PR_TRUE, NULL);

    PORT_Free(rawArray);
  }
  
  return NS_OK;
}
示例#5
0
static SECStatus
ssl3_CngPlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf,
                           PRBool isTLS, KeyType keyType)
{
    SECStatus       rv                = SECFailure;
    SECURITY_STATUS ncrypt_status;
    PRBool          doDerEncode       = PR_FALSE;
    SECItem         hashItem;
    DWORD           signatureLen      = 0;
    DWORD           dwFlags           = 0;
    VOID           *pPaddingInfo      = NULL;

    /* Always encode using PKCS#1 block type. */
    BCRYPT_PKCS1_PADDING_INFO rsaPaddingInfo;

    if (key->dwKeySpec != CERT_NCRYPT_KEY_SPEC) {
        PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0);
        return SECFailure;
    }
    if (ssl_InitCng() != SECSuccess) {
        PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0);
        return SECFailure;
    }

    switch (keyType) {
        case rsaKey:
            switch (hash->hashAlg) {
                case SEC_OID_UNKNOWN:
                    /* No OID/encoded DigestInfo. */
                    rsaPaddingInfo.pszAlgId = NULL;
                    break;
                case SEC_OID_SHA1:
                    rsaPaddingInfo.pszAlgId = BCRYPT_SHA1_ALGORITHM;
                    break;
                case SEC_OID_SHA256:
                    rsaPaddingInfo.pszAlgId = BCRYPT_SHA256_ALGORITHM;
                    break;
                case SEC_OID_SHA384:
                    rsaPaddingInfo.pszAlgId = BCRYPT_SHA384_ALGORITHM;
                    break;
                case SEC_OID_SHA512:
                    rsaPaddingInfo.pszAlgId = BCRYPT_SHA512_ALGORITHM;
                    break;
                default:
                    PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM);
                    return SECFailure;
            }
            hashItem.data = hash->u.raw;
            hashItem.len  = hash->len;
            dwFlags       = BCRYPT_PAD_PKCS1;
            pPaddingInfo  = &rsaPaddingInfo;
            break;
        case dsaKey:
        case ecKey:
            if (keyType == ecKey) {
                doDerEncode = PR_TRUE;
            } else {
                doDerEncode = isTLS;
            }
            if (hash->hashAlg == SEC_OID_UNKNOWN) {
                hashItem.data = hash->u.s.sha;
                hashItem.len  = sizeof(hash->u.s.sha);
            } else {
                hashItem.data = hash->u.raw;
                hashItem.len  = hash->len;
            }
            break;
        default:
            PORT_SetError(SEC_ERROR_INVALID_KEY);
            goto done;
    }
    PRINT_BUF(60, (NULL, "hash(es) to be signed", hashItem.data, hashItem.len));

    ncrypt_status = (*pNCryptSignHash)(key->hNCryptKey, pPaddingInfo,
                                       (PBYTE)hashItem.data, hashItem.len,
                                       NULL, 0, &signatureLen, dwFlags);
    if (FAILED(ncrypt_status) || signatureLen == 0) {
        PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, ncrypt_status);
        goto done;
    }

    buf->data = (unsigned char *)PORT_Alloc(signatureLen);
    if (!buf->data) {
        goto done;    /* error code was set. */
    }

    ncrypt_status = (*pNCryptSignHash)(key->hNCryptKey, pPaddingInfo,
                                       (PBYTE)hashItem.data, hashItem.len,
                                       (PBYTE)buf->data, signatureLen,
                                       &signatureLen, dwFlags);
    if (FAILED(ncrypt_status) || signatureLen == 0) {
        PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, ncrypt_status);
        goto done;
    }

    buf->len = signatureLen;

    if (doDerEncode) {
        SECItem   derSig = {siBuffer, NULL, 0};

        /* This also works for an ECDSA signature */
        rv = DSAU_EncodeDerSigWithLen(&derSig, buf, buf->len);
        if (rv == SECSuccess) {
            PORT_Free(buf->data);     /* discard unencoded signature. */
            *buf = derSig;            /* give caller encoded signature. */
        } else if (derSig.data) {
            PORT_Free(derSig.data);
        }
    } else {
        rv = SECSuccess;
    }

    PRINT_BUF(60, (NULL, "signed hashes", buf->data, buf->len));

done:
    if (rv != SECSuccess && buf->data) {
        PORT_Free(buf->data);
        buf->data = NULL;
        buf->len = 0;
    }

    return rv;
}
示例#6
0
static
void*
my_alloc_func(void*opaque, uInt items, uInt size)
{
    return PORT_Alloc(items * size);
}
示例#7
0
SECStatus
SSL_ExportKeyingMaterial(PRFileDesc *fd,
                         const char *label, unsigned int labelLen,
                         PRBool hasContext,
                         const unsigned char *context, unsigned int contextLen,
                         unsigned char *out, unsigned int outLen)
{
    sslSocket *ss;
    unsigned char *val = NULL;
    unsigned int valLen, i;
    SECStatus rv = SECFailure;

    ss = ssl_FindSocket(fd);
    if (!ss) {
        SSL_DBG(("%d: SSL[%d]: bad socket in ExportKeyingMaterial",
                 SSL_GETPID(), fd));
        return SECFailure;
    }

    if (!label || !labelLen || !out || !outLen ||
            (hasContext && (!context || !contextLen))) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
        return tls13_Exporter(ss, ss->ssl3.hs.exporterSecret,
                              label, labelLen,
                              context, hasContext ? contextLen : 0,
                              out, outLen);
    }

    /* construct PRF arguments */
    valLen = SSL3_RANDOM_LENGTH * 2;
    if (hasContext) {
        valLen += 2 /* PRUint16 length */ + contextLen;
    }
    val = PORT_Alloc(valLen);
    if (!val) {
        return SECFailure;
    }
    i = 0;
    PORT_Memcpy(val + i, &ss->ssl3.hs.client_random.rand, SSL3_RANDOM_LENGTH);
    i += SSL3_RANDOM_LENGTH;
    PORT_Memcpy(val + i, &ss->ssl3.hs.server_random.rand, SSL3_RANDOM_LENGTH);
    i += SSL3_RANDOM_LENGTH;
    if (hasContext) {
        val[i++] = contextLen >> 8;
        val[i++] = contextLen;
        PORT_Memcpy(val + i, context, contextLen);
        i += contextLen;
    }
    PORT_Assert(i == valLen);

    /* Allow TLS keying material to be exported sooner, when the master
     * secret is available and we have sent ChangeCipherSpec.
     */
    ssl_GetSpecReadLock(ss);
    if (!ss->ssl3.cwSpec->master_secret && !ss->ssl3.cwSpec->msItem.len) {
        PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED);
        rv = SECFailure;
    } else {
        rv = ssl3_TLSPRFWithMasterSecret(ss, ss->ssl3.cwSpec, label, labelLen,
                                         val, valLen, out, outLen);
    }
    ssl_ReleaseSpecReadLock(ss);

    PORT_ZFree(val, valLen);
    return rv;
}
示例#8
0
SECStatus
SECU_ParseCommandLine(int argc, char **argv, char *progName,
                      const secuCommand *cmd)
{
    PRBool found;
    PLOptState *optstate;
    PLOptStatus status;
    char *optstring;
    PLLongOpt *longopts = NULL;
    int i, j;
    int lcmd = 0, lopt = 0;

    PR_ASSERT(HasNoDuplicates(cmd->commands, cmd->numCommands));
    PR_ASSERT(HasNoDuplicates(cmd->options, cmd->numOptions));

    optstring = (char *)PORT_Alloc(cmd->numCommands + 2 * cmd->numOptions + 1);
    if (optstring == NULL)
        return SECFailure;

    j = 0;
    for (i = 0; i < cmd->numCommands; i++) {
        if (cmd->commands[i].flag) /* single character option ? */
            optstring[j++] = cmd->commands[i].flag;
        if (cmd->commands[i].longform)
            lcmd++;
    }
    for (i = 0; i < cmd->numOptions; i++) {
        if (cmd->options[i].flag) {
            optstring[j++] = cmd->options[i].flag;
            if (cmd->options[i].needsArg)
                optstring[j++] = ':';
        }
        if (cmd->options[i].longform)
            lopt++;
    }

    optstring[j] = '\0';

    if (lcmd + lopt > 0) {
        longopts = PORT_NewArray(PLLongOpt, lcmd + lopt + 1);
        if (!longopts) {
            PORT_Free(optstring);
            return SECFailure;
        }

        j = 0;
        for (i = 0; j < lcmd && i < cmd->numCommands; i++) {
            if (cmd->commands[i].longform) {
                longopts[j].longOptName = cmd->commands[i].longform;
                longopts[j].longOption = 0;
                longopts[j++].valueRequired = cmd->commands[i].needsArg;
            }
        }
        lopt += lcmd;
        for (i = 0; j < lopt && i < cmd->numOptions; i++) {
            if (cmd->options[i].longform) {
                longopts[j].longOptName = cmd->options[i].longform;
                longopts[j].longOption = 0;
                longopts[j++].valueRequired = cmd->options[i].needsArg;
            }
        }
        longopts[j].longOptName = NULL;
    }

    optstate = PL_CreateLongOptState(argc, argv, optstring, longopts);
    if (!optstate) {
        PORT_Free(optstring);
        PORT_Free(longopts);
        return SECFailure;
    }
    /* Parse command line arguments */
    while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
        const char *optstatelong;
        char option = optstate->option;

        /*  positional parameter, single-char option or long opt? */
        if (optstate->longOptIndex == -1) {
            /* not a long opt */
            if (option == '\0')
                continue; /* it's a positional parameter */
            optstatelong = "";
        } else {
            /* long opt */
            if (option == '\0')
                option = '\377'; /* force unequal with all flags */
            optstatelong = longopts[optstate->longOptIndex].longOptName;
        }

        found = PR_FALSE;

        for (i = 0; i < cmd->numCommands; i++) {
            if (cmd->commands[i].flag == option ||
                cmd->commands[i].longform == optstatelong) {
                cmd->commands[i].activated = PR_TRUE;
                if (optstate->value) {
                    cmd->commands[i].arg = (char *)optstate->value;
                }
                found = PR_TRUE;
                break;
            }
        }

        if (found)
            continue;

        for (i = 0; i < cmd->numOptions; i++) {
            if (cmd->options[i].flag == option ||
                cmd->options[i].longform == optstatelong) {
                cmd->options[i].activated = PR_TRUE;
                if (optstate->value) {
                    cmd->options[i].arg = (char *)optstate->value;
                } else if (cmd->options[i].needsArg) {
                    status = PL_OPT_BAD;
                    goto loser;
                }
                found = PR_TRUE;
                break;
            }
        }

        if (!found) {
            status = PL_OPT_BAD;
            break;
        }
    }

loser:
    PL_DestroyOptState(optstate);
    PORT_Free(optstring);
    if (longopts)
        PORT_Free(longopts);
    if (status == PL_OPT_BAD)
        return SECFailure;
    return SECSuccess;
}
示例#9
0
文件: secitem.c 项目: emaldona/nss
SECItem *
SECITEM_AllocItem(PLArenaPool *arena, SECItem *item, unsigned int len)
{
    SECItem *result = NULL;
    void *mark = NULL;

    if (arena != NULL) {
        mark = PORT_ArenaMark(arena);
    }

    if (item == NULL) {
        if (arena != NULL) {
            result = PORT_ArenaZAlloc(arena, sizeof(SECItem));
        } else {
            result = PORT_ZAlloc(sizeof(SECItem));
        }
        if (result == NULL) {
            goto loser;
        }
    } else {
        PORT_Assert(item->data == NULL);
        result = item;
    }

    result->len = len;
    if (len) {
        if (arena != NULL) {
            result->data = PORT_ArenaAlloc(arena, len);
        } else {
            result->data = PORT_Alloc(len);
        }
        if (result->data == NULL) {
            goto loser;
        }
    } else {
        result->data = NULL;
    }

    if (mark) {
        PORT_ArenaUnmark(arena, mark);
    }
    return (result);

loser:
    if (arena != NULL) {
        if (mark) {
            PORT_ArenaRelease(arena, mark);
        }
        if (item != NULL) {
            item->data = NULL;
            item->len = 0;
        }
    } else {
        if (result != NULL) {
            SECITEM_FreeItem(result, (item == NULL) ? PR_TRUE : PR_FALSE);
        }
        /*
         * If item is not NULL, the above has set item->data and
         * item->len to 0.
         */
    }
    return (NULL);
}
示例#10
0
/*
 * load a new module into our address space and initialize it.
 */
SECStatus
secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule) {
    PRLibrary *library = NULL;
    CK_C_GetFunctionList entry = NULL;
    CK_INFO info;
    CK_ULONG slotCount = 0;
    SECStatus rv;
    PRBool alreadyLoaded = PR_FALSE;
    char *disableUnload = NULL;

    if (mod->loaded) return SECSuccess;

    /* intenal modules get loaded from their internal list */
    if (mod->internal && (mod->dllName == NULL)) {
#ifdef NSS_STATIC
    if (mod->isFIPS) {
        entry = FC_GetFunctionList;
    } else {
        entry = NSC_GetFunctionList;
    }
    if (mod->isModuleDB) {
        mod->moduleDBFunc = NSC_ModuleDBFunc;
    }
#else
    /*
     * Loads softoken as a dynamic library,
     * even though the rest of NSS assumes this as the "internal" module.
     */
    if (!softokenLib && 
        PR_SUCCESS != PR_CallOnce(&loadSoftokenOnce, &softoken_LoadDSO))
        return SECFailure;

    PR_ATOMIC_INCREMENT(&softokenLoadCount);

    if (mod->isFIPS) {
        entry = (CK_C_GetFunctionList) 
                    PR_FindSymbol(softokenLib, "FC_GetFunctionList");
    } else {
        entry = (CK_C_GetFunctionList) 
                    PR_FindSymbol(softokenLib, "NSC_GetFunctionList");
    }

    if (!entry)
        return SECFailure;

    if (mod->isModuleDB) {
        mod->moduleDBFunc = (CK_C_GetFunctionList) 
                    PR_FindSymbol(softokenLib, "NSC_ModuleDBFunc");
    }
#endif

    if (mod->moduleDBOnly) {
        mod->loaded = PR_TRUE;
        return SECSuccess;
    }
    } else {
	/* Not internal, load the DLL and look up C_GetFunctionList */
	if (mod->dllName == NULL) {
	    return SECFailure;
	}
#if defined(NSS_STATIC) && !defined(NSS_DISABLE_ROOT_CERTS)
	if (strstr(mod->dllName, "nssckbi") != NULL) {
	    mod->library = NULL;
	    PORT_Assert(!mod->moduleDBOnly);
	    entry = builtinsC_GetFunctionList;
	    PORT_Assert(!mod->isModuleDB);
	    goto library_loaded;
	}
#endif

	/* load the library. If this succeeds, then we have to remember to
	 * unload the library if anything goes wrong from here on out...
	 */
	library = PR_LoadLibrary(mod->dllName);
	mod->library = (void *)library;

	if (library == NULL) {
	    return SECFailure;
	}

	/*
	 * now we need to get the entry point to find the function pointers
	 */
	if (!mod->moduleDBOnly) {
	    entry = (CK_C_GetFunctionList)
			PR_FindSymbol(library, "C_GetFunctionList");
	}
	if (mod->isModuleDB) {
	    mod->moduleDBFunc = (void *)
			PR_FindSymbol(library, "NSS_ReturnModuleSpecData");
	}
#if defined(NSS_STATIC) && !defined(NSS_DISABLE_ROOT_CERTS)
library_loaded:
#endif
	if (mod->moduleDBFunc == NULL) mod->isModuleDB = PR_FALSE;
	if (entry == NULL) {
	    if (mod->isModuleDB) {
		mod->loaded = PR_TRUE;
		mod->moduleDBOnly = PR_TRUE;
		return SECSuccess;
	    }
	    PR_UnloadLibrary(library);
	    return SECFailure;
	}
    }

    /*
     * We need to get the function list
     */
    if ((*entry)((CK_FUNCTION_LIST_PTR *)&mod->functionList) != CKR_OK) 
								goto fail;

#ifdef DEBUG_MODULE
    if (PR_TRUE) {
	modToDBG = PR_GetEnv("NSS_DEBUG_PKCS11_MODULE");
	if (modToDBG && strcmp(mod->commonName, modToDBG) == 0) {
	    mod->functionList = (void *)nss_InsertDeviceLog(
	                           (CK_FUNCTION_LIST_PTR)mod->functionList);
	}
    }
#endif

    mod->isThreadSafe = PR_TRUE;

    /* Now we initialize the module */
    rv = secmod_ModuleInit(mod, oldModule, &alreadyLoaded);
    if (rv != SECSuccess) {
	goto fail;
    }

    /* module has been reloaded, this module itself is done, 
     * return to the caller */
    if (mod->functionList == NULL) {
	mod->loaded = PR_TRUE; /* technically the module is loaded.. */
	return SECSuccess;
    }

    /* check the version number */
    if (PK11_GETTAB(mod)->C_GetInfo(&info) != CKR_OK) goto fail2;
    if (info.cryptokiVersion.major != 2) goto fail2;
    /* all 2.0 are a priori *not* thread safe */
    if (info.cryptokiVersion.minor < 1) {
        if (!loadSingleThreadedModules) {
            PORT_SetError(SEC_ERROR_INCOMPATIBLE_PKCS11);
            goto fail2;
        } else {
            mod->isThreadSafe = PR_FALSE;
        }
    }
    mod->cryptokiVersion = info.cryptokiVersion;

    /* If we don't have a common name, get it from the PKCS 11 module */
    if ((mod->commonName == NULL) || (mod->commonName[0] == 0)) {
	mod->commonName = PK11_MakeString(mod->arena,NULL,
	   (char *)info.libraryDescription, sizeof(info.libraryDescription));
	if (mod->commonName == NULL) goto fail2;
    }
    

    /* initialize the Slots */
    if (PK11_GETTAB(mod)->C_GetSlotList(CK_FALSE, NULL, &slotCount) == CKR_OK) {
	CK_SLOT_ID *slotIDs;
	int i;
	CK_RV crv;

	mod->slots = (PK11SlotInfo **)PORT_ArenaAlloc(mod->arena,
					sizeof(PK11SlotInfo *) * slotCount);
	if (mod->slots == NULL) goto fail2;

	slotIDs = (CK_SLOT_ID *) PORT_Alloc(sizeof(CK_SLOT_ID)*slotCount);
	if (slotIDs == NULL) {
	    goto fail2;
	}  
	crv = PK11_GETTAB(mod)->C_GetSlotList(CK_FALSE, slotIDs, &slotCount);
	if (crv != CKR_OK) {
	    PORT_Free(slotIDs);
	    goto fail2;
	}

	/* Initialize each slot */
	for (i=0; i < (int)slotCount; i++) {
	    mod->slots[i] = PK11_NewSlotInfo(mod);
	    PK11_InitSlot(mod,slotIDs[i],mod->slots[i]);
	    /* look down the slot info table */
	    PK11_LoadSlotList(mod->slots[i],mod->slotInfo,mod->slotInfoCount);
	    SECMOD_SetRootCerts(mod->slots[i],mod);
	    /* explicitly mark the internal slot as such if IsInternalKeySlot()
	     * is set */
	    if (secmod_IsInternalKeySlot(mod) && (i == (mod->isFIPS ? 0 : 1))) {
		pk11_SetInternalKeySlotIfFirst(mod->slots[i]);
	    } 
	}
	mod->slotCount = slotCount;
	mod->slotInfoCount = 0;
	PORT_Free(slotIDs);
    }
    
    mod->loaded = PR_TRUE;
    mod->moduleID = nextModuleID++;
    return SECSuccess;
fail2:
    if (enforceAlreadyInitializedError || (!alreadyLoaded)) {
        PK11_GETTAB(mod)->C_Finalize(NULL);
    }
fail:
    mod->functionList = NULL;
    disableUnload = PR_GetEnv("NSS_DISABLE_UNLOAD");
    if (library && !disableUnload) {
        PR_UnloadLibrary(library);
    }
    return SECFailure;
}
示例#11
0
文件: derive.c 项目: 7kbird/chrome
SECStatus 
SSL_CanBypass(CERTCertificate *cert, SECKEYPrivateKey *srvPrivkey,
	      PRUint32 protocolmask, PRUint16 *ciphersuites, int nsuites,
              PRBool *pcanbypass, void *pwArg)
{
#ifdef NO_PKCS11_BYPASS
    if (!pcanbypass) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }
    *pcanbypass = PR_FALSE;
    return SECSuccess;
#else
    SECStatus	      rv;
    int		      i;
    PRUint16	      suite;
    PK11SymKey *      pms = NULL;
    SECKEYPublicKey * srvPubkey = NULL;
    KeyType	      privKeytype;
    PK11SlotInfo *    slot = NULL;
    SECItem           param;
    CK_VERSION 	      version;
    CK_MECHANISM_TYPE mechanism_array[2];
    SECItem           enc_pms = {siBuffer, NULL, 0};
    PRBool	      isTLS = PR_FALSE;
    SSLCipherSuiteInfo csdef;
    PRBool	      testrsa = PR_FALSE;
    PRBool	      testrsa_export = PR_FALSE;
    PRBool	      testecdh = PR_FALSE;
    PRBool	      testecdhe = PR_FALSE;
#ifdef NSS_ENABLE_ECC
    SECKEYECParams ecParams = { siBuffer, NULL, 0 };
#endif

    if (!cert || !srvPrivkey || !ciphersuites || !pcanbypass) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }
    
    srvPubkey = CERT_ExtractPublicKey(cert);
    if (!srvPubkey)
        return SECFailure;
	
    *pcanbypass = PR_TRUE;
    rv = SECFailure;
    
    /* determine which KEAs to test */
    /* 0 (SSL_NULL_WITH_NULL_NULL) is used as a list terminator because
     * SSL3 and TLS specs forbid negotiating that cipher suite number.
     */
    for (i=0; i < nsuites && (suite = *ciphersuites++) != 0; i++) {
	/* skip SSL2 cipher suites and ones NSS doesn't support */
	if (SSL_GetCipherSuiteInfo(suite, &csdef, sizeof(csdef)) != SECSuccess
	    || SSL_IS_SSL2_CIPHER(suite) )
	    continue;
	switch (csdef.keaType) {
	case ssl_kea_rsa:
	    switch (csdef.cipherSuite) {
	    case TLS_RSA_EXPORT1024_WITH_RC4_56_SHA:
	    case TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA:
	    case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
	    case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
		testrsa_export = PR_TRUE;
	    }
	    if (!testrsa_export)
		testrsa = PR_TRUE;
	    break;
	case ssl_kea_ecdh:
	    if (strcmp(csdef.keaTypeName, "ECDHE") == 0) /* ephemeral? */
		testecdhe = PR_TRUE;
	    else
		testecdh = PR_TRUE;
	    break;
	case ssl_kea_dh:
	    /* this is actually DHE */
	default:
	    continue;
	}
    }
    
    /* For each protocol try to derive and extract an MS.
     * Failure of function any function except MS extract means
     * continue with the next cipher test. Stop testing when the list is
     * exhausted or when the first MS extract--not derive--fails.
     */
    privKeytype = SECKEY_GetPrivateKeyType(srvPrivkey);
    protocolmask &= SSL_CBP_SSL3|SSL_CBP_TLS1_0;
    while (protocolmask) {
	if (protocolmask & SSL_CBP_SSL3) {
	    isTLS = PR_FALSE;
	    protocolmask ^= SSL_CBP_SSL3;
	} else {
	    isTLS = PR_TRUE;
	    protocolmask ^= SSL_CBP_TLS1_0;
	}

	if (privKeytype == rsaKey && testrsa_export) {
	    if (PK11_GetPrivateModulusLen(srvPrivkey) > EXPORT_RSA_KEY_LENGTH) {
		*pcanbypass = PR_FALSE;
		rv = SECSuccess;
		break;
	    } else
		testrsa = PR_TRUE;
	}
	for (; privKeytype == rsaKey && testrsa; ) {
	    /* TLS_RSA */
	    unsigned char     rsaPmsBuf[SSL3_RSA_PMS_LENGTH];
	    unsigned int      outLen = 0;
	    CK_MECHANISM_TYPE target;
	    SECStatus	      irv;
	    
	    mechanism_array[0] = CKM_SSL3_PRE_MASTER_KEY_GEN;
	    mechanism_array[1] = CKM_RSA_PKCS;

	    slot = PK11_GetBestSlotMultiple(mechanism_array, 2, pwArg);
	    if (slot == NULL) {
		PORT_SetError(SSL_ERROR_TOKEN_SLOT_NOT_FOUND);
		break;
	    }

	    /* Generate the pre-master secret ...  (client side) */
	    version.major = 3 /*MSB(clientHelloVersion)*/;
	    version.minor = 0 /*LSB(clientHelloVersion)*/;
	    param.data = (unsigned char *)&version;
	    param.len  = sizeof version;
	    pms = PK11_KeyGen(slot, CKM_SSL3_PRE_MASTER_KEY_GEN, &param, 0, pwArg);
	    PK11_FreeSlot(slot);
	    if (!pms)
		break;
	    /* now wrap it */
	    enc_pms.len  = SECKEY_PublicKeyStrength(srvPubkey);
	    enc_pms.data = (unsigned char*)PORT_Alloc(enc_pms.len);
	    if (enc_pms.data == NULL) {
	        PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
	        break;
	    }
	    irv = PK11_PubWrapSymKey(CKM_RSA_PKCS, srvPubkey, pms, &enc_pms);
	    if (irv != SECSuccess) 
		break;
	    PK11_FreeSymKey(pms);
	    pms = NULL;
	    /* now do the server side--check the triple bypass first */
	    rv = PK11_PrivDecryptPKCS1(srvPrivkey, rsaPmsBuf, &outLen,
				       sizeof rsaPmsBuf,
				       (unsigned char *)enc_pms.data,
				       enc_pms.len);
	    /* if decrypt worked we're done with the RSA test */
	    if (rv == SECSuccess) {
		*pcanbypass = PR_TRUE;
		break;
	    }
	    /* check for fallback to double bypass */
	    target = isTLS ? CKM_TLS_MASTER_KEY_DERIVE
			: CKM_SSL3_MASTER_KEY_DERIVE;
	    pms = PK11_PubUnwrapSymKey(srvPrivkey, &enc_pms,
				       target, CKA_DERIVE, 0);
	    rv = ssl_canExtractMS(pms, isTLS, PR_FALSE, pcanbypass);
	    if (rv == SECSuccess && *pcanbypass == PR_FALSE)
		goto done;
	    break;
	}

	/* Check for NULL to avoid double free. 
	 * SECItem_FreeItem sets data NULL in secitem.c#265 
	 */
	if (enc_pms.data != NULL) {
	    SECITEM_FreeItem(&enc_pms, PR_FALSE);
        }
#ifdef NSS_ENABLE_ECC
	for (; (privKeytype == ecKey && ( testecdh || testecdhe)) ||
	       (privKeytype == rsaKey && testecdhe); ) {
	    CK_MECHANISM_TYPE target;
	    SECKEYPublicKey  *keapub = NULL;
	    SECKEYPrivateKey *keapriv;
	    SECKEYPublicKey  *cpub = NULL; /* client's ephemeral ECDH keys */
	    SECKEYPrivateKey *cpriv = NULL;
	    SECKEYECParams   *pecParams = NULL;

	    if (privKeytype == ecKey && testecdhe) {
		/* TLS_ECDHE_ECDSA */
		pecParams = &srvPubkey->u.ec.DEREncodedParams;
	    } else if (privKeytype == rsaKey && testecdhe) {
		/* TLS_ECDHE_RSA */
		ECName       ec_curve;
		int		 serverKeyStrengthInBits;
		int		 signatureKeyStrength;
		int		 requiredECCbits;

		/* find a curve of equivalent strength to the RSA key's */
		requiredECCbits = PK11_GetPrivateModulusLen(srvPrivkey);
		if (requiredECCbits < 0)
		    break;
		requiredECCbits *= BPB;
		serverKeyStrengthInBits = srvPubkey->u.rsa.modulus.len;
		if (srvPubkey->u.rsa.modulus.data[0] == 0) {
		    serverKeyStrengthInBits--;
		}
		/* convert to strength in bits */
		serverKeyStrengthInBits *= BPB;

		signatureKeyStrength =
		    SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyStrengthInBits);

		if ( requiredECCbits > signatureKeyStrength ) 
		     requiredECCbits = signatureKeyStrength;

		ec_curve =
		    ssl3_GetCurveWithECKeyStrength(
					ssl3_GetSupportedECCurveMask(NULL),
				  	requiredECCbits);
		rv = ssl3_ECName2Params(NULL, ec_curve, &ecParams);
		if (rv == SECFailure) {
		    break;
		}
		pecParams = &ecParams;
	    }

	    if (testecdhe) {
		/* generate server's ephemeral keys */
		keapriv = SECKEY_CreateECPrivateKey(pecParams, &keapub, NULL); 
		if (!keapriv || !keapub) {
		    if (keapriv)
			SECKEY_DestroyPrivateKey(keapriv);
		    if (keapub)
			SECKEY_DestroyPublicKey(keapub);
		    PORT_SetError(SEC_ERROR_KEYGEN_FAIL);
		    rv = SECFailure;
		    break;
		}
	    } else {
		/* TLS_ECDH_ECDSA */
		keapub = srvPubkey;
		keapriv = srvPrivkey;
		pecParams = &srvPubkey->u.ec.DEREncodedParams;
	    }

	    /* perform client side ops */
	    /* generate a pair of ephemeral keys using server's parms */
	    cpriv = SECKEY_CreateECPrivateKey(pecParams, &cpub, NULL);
	    if (!cpriv || !cpub) {
		if (testecdhe) {
		    SECKEY_DestroyPrivateKey(keapriv);
		    SECKEY_DestroyPublicKey(keapub);
		}
		PORT_SetError(SEC_ERROR_KEYGEN_FAIL);
		rv = SECFailure;
		break;
	    }
	    /* now do the server side */
	    /* determine the PMS using client's public value */
	    target = isTLS ? CKM_TLS_MASTER_KEY_DERIVE_DH
			   : CKM_SSL3_MASTER_KEY_DERIVE_DH;
	    pms = PK11_PubDeriveWithKDF(keapriv, cpub, PR_FALSE, NULL, NULL,
				    CKM_ECDH1_DERIVE,
				    target,
				    CKA_DERIVE, 0, CKD_NULL, NULL, NULL);
	    rv = ssl_canExtractMS(pms, isTLS, PR_TRUE, pcanbypass);
	    SECKEY_DestroyPrivateKey(cpriv);
	    SECKEY_DestroyPublicKey(cpub);
	    if (testecdhe) {
		SECKEY_DestroyPrivateKey(keapriv);
		SECKEY_DestroyPublicKey(keapub);
	    }
	    if (rv == SECSuccess && *pcanbypass == PR_FALSE)
		goto done;
	    break;
	}
	/* Check for NULL to avoid double free. */
	if (ecParams.data != NULL) {
	    PORT_Free(ecParams.data);
	    ecParams.data = NULL;
	}
#endif /* NSS_ENABLE_ECC */
	if (pms)
	    PK11_FreeSymKey(pms);
    }

    /* *pcanbypass has been set */
    rv = SECSuccess;
    
  done:
    if (pms)
	PK11_FreeSymKey(pms);

    /* Check for NULL to avoid double free. 
     * SECItem_FreeItem sets data NULL in secitem.c#265 
     */
    if (enc_pms.data != NULL) {
    	SECITEM_FreeItem(&enc_pms, PR_FALSE);
    }
#ifdef NSS_ENABLE_ECC
    if (ecParams.data != NULL) {
        PORT_Free(ecParams.data);
        ecParams.data = NULL;
    }
#endif /* NSS_ENABLE_ECC */

    if (srvPubkey) {
    	SECKEY_DestroyPublicKey(srvPubkey);
	srvPubkey = NULL;
    }


    return rv;
#endif /* NO_PKCS11_BYPASS */
}
示例#12
0
char *
CERT_FormatName(CERTName *name)
{
    CERTRDN **rdns;
    CERTRDN *rdn;
    CERTAVA **avas;
    CERTAVA *ava;
    char *buf = 0;
    char *tmpbuf = 0;
    SECItem *cn = 0;
    SECItem *email = 0;
    SECItem *org = 0;
    SECItem *loc = 0;
    SECItem *state = 0;
    SECItem *country = 0;
    SECItem *dq = 0;

    unsigned len = 0;
    int tag;
    int i;
    int ou_count = 0;
    int dc_count = 0;
    PRBool first;
    SECItem *orgunit[MAX_OUS];
    SECItem *dc[MAX_DC];

    /* Loop over name components and gather the interesting ones */
    rdns = name->rdns;
    while ((rdn = *rdns++) != 0) {
        avas = rdn->avas;
        while ((ava = *avas++) != 0) {
            tag = CERT_GetAVATag(ava);
            switch (tag) {
                case SEC_OID_AVA_COMMON_NAME:
                    if (cn) {
                        break;
                    }
                    cn = CERT_DecodeAVAValue(&ava->value);
                    if (!cn) {
                        goto loser;
                    }
                    len += cn->len;
                    break;
                case SEC_OID_AVA_COUNTRY_NAME:
                    if (country) {
                        break;
                    }
                    country = CERT_DecodeAVAValue(&ava->value);
                    if (!country) {
                        goto loser;
                    }
                    len += country->len;
                    break;
                case SEC_OID_AVA_LOCALITY:
                    if (loc) {
                        break;
                    }
                    loc = CERT_DecodeAVAValue(&ava->value);
                    if (!loc) {
                        goto loser;
                    }
                    len += loc->len;
                    break;
                case SEC_OID_AVA_STATE_OR_PROVINCE:
                    if (state) {
                        break;
                    }
                    state = CERT_DecodeAVAValue(&ava->value);
                    if (!state) {
                        goto loser;
                    }
                    len += state->len;
                    break;
                case SEC_OID_AVA_ORGANIZATION_NAME:
                    if (org) {
                        break;
                    }
                    org = CERT_DecodeAVAValue(&ava->value);
                    if (!org) {
                        goto loser;
                    }
                    len += org->len;
                    break;
                case SEC_OID_AVA_DN_QUALIFIER:
                    if (dq) {
                        break;
                    }
                    dq = CERT_DecodeAVAValue(&ava->value);
                    if (!dq) {
                        goto loser;
                    }
                    len += dq->len;
                    break;
                case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME:
                    if (ou_count < MAX_OUS) {
                        orgunit[ou_count] = CERT_DecodeAVAValue(&ava->value);
                        if (!orgunit[ou_count]) {
                            goto loser;
                        }
                        len += orgunit[ou_count++]->len;
                    }
                    break;
                case SEC_OID_AVA_DC:
                    if (dc_count < MAX_DC) {
                        dc[dc_count] = CERT_DecodeAVAValue(&ava->value);
                        if (!dc[dc_count]) {
                            goto loser;
                        }
                        len += dc[dc_count++]->len;
                    }
                    break;
                case SEC_OID_PKCS9_EMAIL_ADDRESS:
                case SEC_OID_RFC1274_MAIL:
                    if (email) {
                        break;
                    }
                    email = CERT_DecodeAVAValue(&ava->value);
                    if (!email) {
                        goto loser;
                    }
                    len += email->len;
                    break;
                default:
                    break;
            }
        }
    }

    /* XXX - add some for formatting */
    len += 128;

    /* allocate buffer */
    buf = (char *)PORT_Alloc(len);
    if (!buf) {
        goto loser;
    }

    tmpbuf = buf;

    if (cn) {
        PORT_Memcpy(tmpbuf, cn->data, cn->len);
        tmpbuf += cn->len;
        PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
        tmpbuf += BREAKLEN;
    }
    if (email) {
        PORT_Memcpy(tmpbuf, email->data, email->len);
        tmpbuf += (email->len);
        PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
        tmpbuf += BREAKLEN;
    }
    for (i = ou_count - 1; i >= 0; i--) {
        PORT_Memcpy(tmpbuf, orgunit[i]->data, orgunit[i]->len);
        tmpbuf += (orgunit[i]->len);
        PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
        tmpbuf += BREAKLEN;
    }
    if (dq) {
        PORT_Memcpy(tmpbuf, dq->data, dq->len);
        tmpbuf += (dq->len);
        PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
        tmpbuf += BREAKLEN;
    }
    if (org) {
        PORT_Memcpy(tmpbuf, org->data, org->len);
        tmpbuf += (org->len);
        PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
        tmpbuf += BREAKLEN;
    }
    for (i = dc_count - 1; i >= 0; i--) {
        PORT_Memcpy(tmpbuf, dc[i]->data, dc[i]->len);
        tmpbuf += (dc[i]->len);
        PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
        tmpbuf += BREAKLEN;
    }
    first = PR_TRUE;
    if (loc) {
        PORT_Memcpy(tmpbuf, loc->data, loc->len);
        tmpbuf += (loc->len);
        first = PR_FALSE;
    }
    if (state) {
        if (!first) {
            PORT_Memcpy(tmpbuf, COMMA, COMMALEN);
            tmpbuf += COMMALEN;
        }
        PORT_Memcpy(tmpbuf, state->data, state->len);
        tmpbuf += (state->len);
        first = PR_FALSE;
    }
    if (country) {
        if (!first) {
            PORT_Memcpy(tmpbuf, COMMA, COMMALEN);
            tmpbuf += COMMALEN;
        }
        PORT_Memcpy(tmpbuf, country->data, country->len);
        tmpbuf += (country->len);
        first = PR_FALSE;
    }
    if (!first) {
        PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
        tmpbuf += BREAKLEN;
    }

    *tmpbuf = 0;

/* fall through and clean */
loser:
    if (cn) {
        SECITEM_FreeItem(cn, PR_TRUE);
    }
    if (email) {
        SECITEM_FreeItem(email, PR_TRUE);
    }
    for (i = ou_count - 1; i >= 0; i--) {
        SECITEM_FreeItem(orgunit[i], PR_TRUE);
    }
    if (dq) {
        SECITEM_FreeItem(dq, PR_TRUE);
    }
    if (org) {
        SECITEM_FreeItem(org, PR_TRUE);
    }
    for (i = dc_count - 1; i >= 0; i--) {
        SECITEM_FreeItem(dc[i], PR_TRUE);
    }
    if (loc) {
        SECITEM_FreeItem(loc, PR_TRUE);
    }
    if (state) {
        SECITEM_FreeItem(state, PR_TRUE);
    }
    if (country) {
        SECITEM_FreeItem(country, PR_TRUE);
    }

    return (buf);
}
示例#13
0
/*
 * SecCmsDigestContextStartMultiple - start digest calculation using all the
 *  digest algorithms in "digestalgs" in parallel.
 */
SecCmsDigestContextRef
SecCmsDigestContextStartMultiple(SECAlgorithmID **digestalgs)
{
    SecCmsDigestContextRef cmsdigcx;
    CSSM_CC_HANDLE digobj;
    int digcnt;
    int i;

    digcnt = (digestalgs == NULL) ? 0 : SecCmsArrayCount((void **)digestalgs);

    cmsdigcx = (SecCmsDigestContextRef)PORT_Alloc(sizeof(struct SecCmsDigestContextStr));
    if (cmsdigcx == NULL)
	return NULL;

    if (digcnt > 0) {
        /* Security check to prevent under-allocation */
        if (digcnt >= (int)(INT_MAX/sizeof(CSSM_CC_HANDLE))) {
            goto loser;
        }
	cmsdigcx->digobjs = (CSSM_CC_HANDLE *)PORT_Alloc(digcnt * sizeof(CSSM_CC_HANDLE));
	if (cmsdigcx->digobjs == NULL)
	    goto loser;
    }

    cmsdigcx->digcnt = 0;

    /*
     * Create a digest object context for each algorithm.
     */
    for (i = 0; i < digcnt; i++) {
	digobj = SecCmsUtilGetHashObjByAlgID(digestalgs[i]);
	/*
	 * Skip any algorithm we do not even recognize; obviously,
	 * this could be a problem, but if it is critical then the
	 * result will just be that the signature does not verify.
	 * We do not necessarily want to error out here, because
	 * the particular algorithm may not actually be important,
	 * but we cannot know that until later.
	 */
	if (digobj)
        {
            CSSM_RETURN result;
	    result = CSSM_DigestDataInit(digobj);
            if (result != CSSM_OK)
            {
                goto loser;
            }
        }
        
	cmsdigcx->digobjs[cmsdigcx->digcnt] = digobj;
	cmsdigcx->digcnt++;
    }

    cmsdigcx->saw_contents = PR_FALSE;

    return cmsdigcx;

loser:
    if (cmsdigcx) {
	if (cmsdigcx->digobjs)
	    PORT_Free(cmsdigcx->digobjs);
    }
    return NULL;
}
示例#14
0
/* Time iter repetitions of operation op. */
SECStatus
M_TimeOperation(void (*threadFunc)(void *),
                op_func opfunc, char *op, void *param1, void *param2,
                void *param3, int iters, int numThreads, PRLock *lock,
                CK_SESSION_HANDLE session, int isSign, double *rate)
{
    double dUserTime;
    int i, total;
    PRIntervalTime startTime, totalTime;
    PRThread **threadIDs;
    ThreadData *threadData;
    pk11_op_func pk11_op = (pk11_op_func)opfunc;
    SECStatus rv;

    /* verify operation works before testing performance */
    if (session) {
        rv = (*pk11_op)(session, param1, param2, param3);
    } else {
        rv = (*opfunc)(param1, param2, param3);
    }
    if (rv != SECSuccess) {
        SECU_PrintError("Error:", op);
        return rv;
    }

    /* get Data structures */
    threadIDs = (PRThread **)PORT_Alloc(numThreads * sizeof(PRThread *));
    threadData = (ThreadData *)PORT_Alloc(numThreads * sizeof(ThreadData));

    startTime = PR_Now();
    if (numThreads == 1) {
        for (i = 0; i < iters; i++) {
            if (session) {
                rv = (*pk11_op)(session, param1, param2, param3);
            } else {
                rv = (*opfunc)(param1, param2, param3);
            }
            if (rv != SECSuccess) {
                PORT_Free(threadIDs);
                PORT_Free(threadData);
                SECU_PrintError("Error:", op);
                return rv;
            }
        }
        total = iters;
    } else {
        for (i = 0; i < numThreads; i++) {
            threadData[i].op = opfunc;
            threadData[i].p1 = (void *)param1;
            threadData[i].p2 = (void *)param2;
            threadData[i].p3 = (void *)param3;
            threadData[i].iters = iters;
            threadData[i].lock = lock;
            threadData[i].isSign = isSign;
            threadIDs[i] = PR_CreateThread(PR_USER_THREAD, threadFunc,
                                           (void *)&threadData[i], PR_PRIORITY_NORMAL,
                                           PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
        }

        total = 0;
        for (i = 0; i < numThreads; i++) {
            PR_JoinThread(threadIDs[i]);
            /* check the status */
            total += threadData[i].count;
        }
    }

    totalTime = PR_Now() - startTime;
    /* SecondsToInterval seems to be broken here ... */
    dUserTime = (double)totalTime / (double)1000000;
    if (dUserTime) {
        printf("    %-15s count:%4d sec: %3.2f op/sec: %6.2f\n",
               op, total, dUserTime, (double)total / dUserTime);
        if (rate) {
            *rate = ((double)total) / dUserTime;
        }
    }
    PORT_Free(threadIDs);
    PORT_Free(threadData);

    return SECSuccess;
}
示例#15
0
int
main(int argc, char **argv)
{
    char *progName;
    FILE *inFile, *outFile;
    CERTCertDBHandle *certHandle;
    struct recipient *recipients, *rcpt;
    PLOptState *optstate;
    PLOptStatus status;
    SECStatus rv;

    progName = strrchr(argv[0], '/');
    progName = progName ? progName + 1 : argv[0];

    inFile = NULL;
    outFile = NULL;
    recipients = NULL;
    rcpt = NULL;

    /*
     * Parse command line arguments
     * XXX This needs to be enhanced to allow selection of algorithms
     * and key sizes (or to look up algorithms and key sizes for each
     * recipient in the magic database).
     */
    optstate = PL_CreateOptState(argc, argv, "d:i:o:r:");
    while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
        switch (optstate->option) {
            case '?':
                Usage(progName);
                break;

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

            case 'i':
                inFile = fopen(optstate->value, "r");
                if (!inFile) {
                    fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
                            progName, optstate->value);
                    return -1;
                }
                break;

            case 'o':
                outFile = fopen(optstate->value, "wb");
                if (!outFile) {
                    fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
                            progName, optstate->value);
                    return -1;
                }
                break;

            case 'r':
                if (rcpt == NULL) {
                    recipients = rcpt = PORT_Alloc(sizeof(struct recipient));
                } else {
                    rcpt->next = PORT_Alloc(sizeof(struct recipient));
                    rcpt = rcpt->next;
                }
                if (rcpt == NULL) {
                    fprintf(stderr, "%s: unable to allocate recipient struct\n",
                            progName);
                    return -1;
                }
                rcpt->nickname = PORT_Strdup(optstate->value);
                rcpt->cert = NULL;
                rcpt->next = NULL;
                break;
        }
    }
    PL_DestroyOptState(optstate);

    if (!recipients)
        Usage(progName);

    if (!inFile)
        inFile = stdin;
    if (!outFile)
        outFile = stdout;

    /* Call the NSS initialization routines */
    PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
    rv = NSS_Init(SECU_ConfigDirectory(NULL));
    if (rv != SECSuccess) {
        SECU_PrintPRandOSError(progName);
        return -1;
    }

    /* open cert database */
    certHandle = CERT_GetDefaultCertDB();
    if (certHandle == NULL) {
        return -1;
    }

    /* find certs */
    for (rcpt = recipients; rcpt != NULL; rcpt = rcpt->next) {
        rcpt->cert = CERT_FindCertByNickname(certHandle, rcpt->nickname);
        if (rcpt->cert == NULL) {
            SECU_PrintError(progName,
                            "the cert for name \"%s\" not found in database",
                            rcpt->nickname);
            return -1;
        }
    }

    if (EncryptFile(outFile, inFile, recipients, progName)) {
        SECU_PrintError(progName, "problem encrypting data");
        return -1;
    }

    /* free certs */
    for (rcpt = recipients; rcpt != NULL; ) {
        struct recipient *next = rcpt->next;
        CERT_DestroyCertificate(rcpt->cert);
        PORT_Free(rcpt->nickname);
        PORT_Free(rcpt);
        rcpt = next;
    }

    if (inFile && inFile != stdin) {
        fclose(inFile);
    }
    if (outFile && outFile != stdout) {
        fclose(outFile);
    }

    if (NSS_Shutdown() != SECSuccess) {
        SECU_PrintError(progName, "NSS shutdown:");
        return -1;
    }

    return 0;
}
示例#16
0
NS_IMETHODIMP
nsNSSCertificateDB::ImportServerCertificate(PRUint8 * data, PRUint32 length, 
                                            nsIInterfaceRequestor *ctx)

{
  nsNSSShutDownPreventionLock locker;
  SECStatus srv = SECFailure;
  nsresult nsrv = NS_OK;
  CERTCertificate * cert;
  SECItem **rawCerts = nsnull;
  int numcerts;
  int i;
  nsNSSCertTrust trust;
  char *serverNickname = nsnull;
 
  PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  if (!arena)
    return NS_ERROR_OUT_OF_MEMORY;

  CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length);
  if (!certCollection) {
    PORT_FreeArena(arena, PR_FALSE);
    return NS_ERROR_FAILURE;
  }
  cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), certCollection->rawCerts,
                          (char *)NULL, PR_FALSE, PR_TRUE);
  if (!cert) {
    nsrv = NS_ERROR_FAILURE;
    goto loser;
  }
  numcerts = certCollection->numcerts;
  rawCerts = (SECItem **) PORT_Alloc(sizeof(SECItem *) * numcerts);
  if ( !rawCerts ) {
    nsrv = NS_ERROR_FAILURE;
    goto loser;
  }

  for ( i = 0; i < numcerts; i++ ) {
    rawCerts[i] = &certCollection->rawCerts[i];
  }

  serverNickname = nsNSSCertificate::defaultServerNickname(cert);
  srv = CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageSSLServer,
             numcerts, rawCerts, NULL, PR_TRUE, PR_FALSE,
             serverNickname);
  PR_FREEIF(serverNickname);
  if ( srv != SECSuccess ) {
    nsrv = NS_ERROR_FAILURE;
    goto loser;
  }

  trust.SetValidServerPeer();
  srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, trust.GetTrust());
  if ( srv != SECSuccess ) {
    nsrv = NS_ERROR_FAILURE;
    goto loser;
  }
loser:
  PORT_Free(rawCerts);
  if (cert)
    CERT_DestroyCertificate(cert);
  if (arena) 
    PORT_FreeArena(arena, PR_TRUE);
  return nsrv;
}
示例#17
0
/*
 *  [noscript] void importEmailCertificates(in charPtr data, in unsigned long length,
 *                                     in nsIInterfaceRequestor ctx);
 */
NS_IMETHODIMP
nsNSSCertificateDB::ImportEmailCertificate(PRUint8 * data, PRUint32 length, 
                                       nsIInterfaceRequestor *ctx)

{
  nsNSSShutDownPreventionLock locker;
  SECStatus srv = SECFailure;
  nsresult nsrv = NS_OK;
  CERTCertDBHandle *certdb;
  CERTCertificate **certArray = NULL;
  CERTCertList *certList = NULL;
  CERTCertListNode *node;
  PRTime now;
  SECCertUsage certusage;
  SECItem **rawArray;
  int numcerts;
  int i;
 
  PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  if (!arena)
    return NS_ERROR_OUT_OF_MEMORY;

  CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length);
  if (!certCollection) {
    PORT_FreeArena(arena, PR_FALSE);
    return NS_ERROR_FAILURE;
  }

  certdb = CERT_GetDefaultCertDB();
  certusage = certUsageEmailRecipient;

  numcerts = certCollection->numcerts;

  rawArray = (SECItem **) PORT_Alloc(sizeof(SECItem *) * numcerts);
  if ( !rawArray ) {
    nsrv = NS_ERROR_FAILURE;
    goto loser;
  }

  for (i=0; i < numcerts; i++) {
    rawArray[i] = &certCollection->rawCerts[i];
  }

  srv = CERT_ImportCerts(certdb, certusage, numcerts, rawArray, 
                         &certArray, PR_FALSE, PR_FALSE, NULL);

  PORT_Free(rawArray);
  rawArray = NULL;

  if (srv != SECSuccess) {
    nsrv = NS_ERROR_FAILURE;
    goto loser;
  }

  // build a CertList for filtering
  certList = CERT_NewCertList();
  if (certList == NULL) {
    nsrv = NS_ERROR_FAILURE;
    goto loser;
  }
  for (i=0; i < numcerts; i++) {
    CERTCertificate *cert = certArray[i];
    if (cert)
      cert = CERT_DupCertificate(cert);
    if (cert)
      CERT_AddCertToListTail(certList, cert);
  }

  /* go down the remaining list of certs and verify that they have
   * valid chains, then import them.
   */
  now = PR_Now();
  for (node = CERT_LIST_HEAD(certList);
       !CERT_LIST_END(node,certList);
       node = CERT_LIST_NEXT(node)) {

    bool alert_and_skip = false;

    if (!node->cert) {
      continue;
    }

    if (CERT_VerifyCert(certdb, node->cert, 
        PR_TRUE, certusage, now, ctx, NULL) != SECSuccess) {
      alert_and_skip = true;
    }

    CERTCertificateList *certChain = nsnull;
    CERTCertificateListCleaner chainCleaner(certChain);

    if (!alert_and_skip) {
      certChain = CERT_CertChainFromCert(node->cert, certusage, PR_FALSE);
      if (!certChain) {
        alert_and_skip = true;
      }
    }

    if (alert_and_skip) {    
      nsCOMPtr<nsIX509Cert> certToShow = new nsNSSCertificate(node->cert);
      DisplayCertificateAlert(ctx, "NotImportingUnverifiedCert", certToShow);
      continue;
    }

    /*
     * CertChain returns an array of SECItems, import expects an array of
     * SECItem pointers. Create the SECItem Pointers from the array of
     * SECItems.
     */
    rawArray = (SECItem **) PORT_Alloc(certChain->len * sizeof(SECItem *));
    if (!rawArray) {
      continue;
    }
    for (i=0; i < certChain->len; i++) {
      rawArray[i] = &certChain->certs[i];
    }
    CERT_ImportCerts(certdb, certusage, certChain->len, 
                            rawArray,  NULL, PR_TRUE, PR_FALSE, NULL);

    CERT_SaveSMimeProfile(node->cert, NULL, NULL);

    PORT_Free(rawArray);
  }

loser:
  if (certArray) {
    CERT_DestroyCertArray(certArray, numcerts);
  }
  if (certList) {
    CERT_DestroyCertList(certList);
  }
  if (arena) 
    PORT_FreeArena(arena, PR_TRUE);
  return nsrv;
}
示例#18
0
/* Computes the ECDSA signature (a concatenation of two values r and s)
 * on the digest using the given key and the random value kb (used in
 * computing s).
 */
SECStatus 
ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, 
    const SECItem *digest, const unsigned char *kb, const int kblen)
{
    SECStatus rv = SECFailure;
#ifdef NSS_ENABLE_ECC
    mp_int x1;
    mp_int d, k;     /* private key, random integer */
    mp_int r, s;     /* tuple (r, s) is the signature */
    mp_int n;
    mp_err err = MP_OKAY;
    ECParams *ecParams = NULL;
    SECItem kGpoint = { siBuffer, NULL, 0};
    int flen = 0;    /* length in bytes of the field size */
    unsigned olen;   /* length in bytes of the base point order */
    unsigned obits;  /* length in bits  of the base point order */

#if EC_DEBUG
    char mpstr[256];
#endif

    /* Initialize MPI integers. */
    /* must happen before the first potential call to cleanup */
    MP_DIGITS(&x1) = 0;
    MP_DIGITS(&d) = 0;
    MP_DIGITS(&k) = 0;
    MP_DIGITS(&r) = 0;
    MP_DIGITS(&s) = 0;
    MP_DIGITS(&n) = 0;

    /* Check args */
    if (!key || !signature || !digest || !kb || (kblen < 0)) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	goto cleanup;
    }

    ecParams = &(key->ecParams);
    flen = (ecParams->fieldID.size + 7) >> 3;
    olen = ecParams->order.len;  
    if (signature->data == NULL) {
	/* a call to get the signature length only */
	goto finish;
    }
    if (signature->len < 2*olen) {
	PORT_SetError(SEC_ERROR_OUTPUT_LEN);
	goto cleanup;
    }


    CHECK_MPI_OK( mp_init(&x1) );
    CHECK_MPI_OK( mp_init(&d) );
    CHECK_MPI_OK( mp_init(&k) );
    CHECK_MPI_OK( mp_init(&r) );
    CHECK_MPI_OK( mp_init(&s) );
    CHECK_MPI_OK( mp_init(&n) );

    SECITEM_TO_MPINT( ecParams->order, &n );
    SECITEM_TO_MPINT( key->privateValue, &d );

    CHECK_MPI_OK( mp_read_unsigned_octets(&k, kb, kblen) );
    /* Make sure k is in the interval [1, n-1] */
    if ((mp_cmp_z(&k) <= 0) || (mp_cmp(&k, &n) >= 0)) {
#if EC_DEBUG
        printf("k is outside [1, n-1]\n");
        mp_tohex(&k, mpstr);
	printf("k : %s \n", mpstr);
        mp_tohex(&n, mpstr);
	printf("n : %s \n", mpstr);
#endif
	PORT_SetError(SEC_ERROR_NEED_RANDOM);
	goto cleanup;
    }

    /*
    ** We do not want timing information to leak the length of k,
    ** so we compute k*G using an equivalent scalar of fixed
    ** bit-length.
    ** Fix based on patch for ECDSA timing attack in the paper
    ** by Billy Bob Brumley and Nicola Tuveri at
    **   http://eprint.iacr.org/2011/232
    **
    ** How do we convert k to a value of a fixed bit-length?
    ** k starts off as an integer satisfying 0 <= k < n.  Hence,
    ** n <= k+n < 2n, which means k+n has either the same number
    ** of bits as n or one more bit than n.  If k+n has the same
    ** number of bits as n, the second addition ensures that the
    ** final value has exactly one more bit than n.  Thus, we
    ** always end up with a value that exactly one more bit than n.
    */
    CHECK_MPI_OK( mp_add(&k, &n, &k) );
    if (mpl_significant_bits(&k) <= mpl_significant_bits(&n)) {
	CHECK_MPI_OK( mp_add(&k, &n, &k) );
    }

    /* 
    ** ANSI X9.62, Section 5.3.2, Step 2
    **
    ** Compute kG
    */
    kGpoint.len = 2*flen + 1;
    kGpoint.data = PORT_Alloc(2*flen + 1);
    if ((kGpoint.data == NULL) ||
	(ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint)
	    != SECSuccess))
	goto cleanup;

    /* 
    ** ANSI X9.62, Section 5.3.3, Step 1
    **
    ** Extract the x co-ordinate of kG into x1
    */
    CHECK_MPI_OK( mp_read_unsigned_octets(&x1, kGpoint.data + 1, 
	                                  (mp_size) flen) );

    /* 
    ** ANSI X9.62, Section 5.3.3, Step 2
    **
    ** r = x1 mod n  NOTE: n is the order of the curve
    */
    CHECK_MPI_OK( mp_mod(&x1, &n, &r) );

    /*
    ** ANSI X9.62, Section 5.3.3, Step 3
    **
    ** verify r != 0 
    */
    if (mp_cmp_z(&r) == 0) {
	PORT_SetError(SEC_ERROR_NEED_RANDOM);
	goto cleanup;
    }

    /*                                  
    ** ANSI X9.62, Section 5.3.3, Step 4
    **
    ** s = (k**-1 * (HASH(M) + d*r)) mod n 
    */
    SECITEM_TO_MPINT(*digest, &s);        /* s = HASH(M)     */

    /* In the definition of EC signing, digests are truncated
     * to the length of n in bits. 
     * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
    CHECK_MPI_OK( (obits = mpl_significant_bits(&n)) );
    if (digest->len*8 > obits) {
	mpl_rsh(&s,&s,digest->len*8 - obits);
    }

#if EC_DEBUG
    mp_todecimal(&n, mpstr);
    printf("n : %s (dec)\n", mpstr);
    mp_todecimal(&d, mpstr);
    printf("d : %s (dec)\n", mpstr);
    mp_tohex(&x1, mpstr);
    printf("x1: %s\n", mpstr);
    mp_todecimal(&s, mpstr);
    printf("digest: %s (decimal)\n", mpstr);
    mp_todecimal(&r, mpstr);
    printf("r : %s (dec)\n", mpstr);
    mp_tohex(&r, mpstr);
    printf("r : %s\n", mpstr);
#endif

    CHECK_MPI_OK( mp_invmod(&k, &n, &k) );      /* k = k**-1 mod n */
    CHECK_MPI_OK( mp_mulmod(&d, &r, &n, &d) );  /* d = d * r mod n */
    CHECK_MPI_OK( mp_addmod(&s, &d, &n, &s) );  /* s = s + d mod n */
    CHECK_MPI_OK( mp_mulmod(&s, &k, &n, &s) );  /* s = s * k mod n */

#if EC_DEBUG
    mp_todecimal(&s, mpstr);
    printf("s : %s (dec)\n", mpstr);
    mp_tohex(&s, mpstr);
    printf("s : %s\n", mpstr);
#endif

    /*
    ** ANSI X9.62, Section 5.3.3, Step 5
    **
    ** verify s != 0
    */
    if (mp_cmp_z(&s) == 0) {
	PORT_SetError(SEC_ERROR_NEED_RANDOM);
	goto cleanup;
    }

   /*
    **
    ** Signature is tuple (r, s)
    */
    CHECK_MPI_OK( mp_to_fixlen_octets(&r, signature->data, olen) );
    CHECK_MPI_OK( mp_to_fixlen_octets(&s, signature->data + olen, olen) );
finish:
    signature->len = 2*olen;

    rv = SECSuccess;
    err = MP_OKAY;
cleanup:
    mp_clear(&x1);
    mp_clear(&d);
    mp_clear(&k);
    mp_clear(&r);
    mp_clear(&s);
    mp_clear(&n);

    if (kGpoint.data) {
	PORT_ZFree(kGpoint.data, 2*flen + 1);
    }

    if (err) {
	MP_TO_SEC_ERROR(err);
	rv = SECFailure;
    }

#if EC_DEBUG
    printf("ECDSA signing with seed %s\n",
	(rv == SECSuccess) ? "succeeded" : "failed");
#endif
#else
    PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
#endif /* NSS_ENABLE_ECC */

   return rv;
}
示例#19
-1
/* 
** Performs an ECDH key derivation by computing the scalar point
** multiplication of privateValue and publicValue (with or without the
** cofactor) and returns the x-coordinate of the resulting elliptic
** curve point in derived secret.  If successful, derivedSecret->data
** is set to the address of the newly allocated buffer containing the
** derived secret, and derivedSecret->len is the size of the secret
** produced. It is the caller's responsibility to free the allocated
** buffer containing the derived secret.
*/
SECStatus 
ECDH_Derive(SECItem  *publicValue, 
            ECParams *ecParams,
            SECItem  *privateValue,
            PRBool    withCofactor,
            SECItem  *derivedSecret)
{
    SECStatus rv = SECFailure;
#ifdef NSS_ENABLE_ECC
    unsigned int len = 0;
    SECItem pointQ = {siBuffer, NULL, 0};
    mp_int k; /* to hold the private value */
    mp_int cofactor;
    mp_err err = MP_OKAY;
#if EC_DEBUG
    int i;
#endif

    if (!publicValue || !ecParams || !privateValue || 
	!derivedSecret) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    }

    MP_DIGITS(&k) = 0;
    memset(derivedSecret, 0, sizeof *derivedSecret);
    len = (ecParams->fieldID.size + 7) >> 3;  
    pointQ.len = 2*len + 1;
    if ((pointQ.data = PORT_Alloc(2*len + 1)) == NULL) goto cleanup;

    CHECK_MPI_OK( mp_init(&k) );
    CHECK_MPI_OK( mp_read_unsigned_octets(&k, privateValue->data, 
	                                  (mp_size) privateValue->len) );

    if (withCofactor && (ecParams->cofactor != 1)) {
	    /* multiply k with the cofactor */
	    MP_DIGITS(&cofactor) = 0;
	    CHECK_MPI_OK( mp_init(&cofactor) );
	    mp_set(&cofactor, ecParams->cofactor);
	    CHECK_MPI_OK( mp_mul(&k, &cofactor, &k) );
    }

    /* Multiply our private key and peer's public point */
    if (ec_points_mul(ecParams, NULL, &k, publicValue, &pointQ) != SECSuccess)
	goto cleanup;
    if (ec_point_at_infinity(&pointQ)) {
	PORT_SetError(SEC_ERROR_BAD_KEY);  /* XXX better error code? */
	goto cleanup;
    }

    /* Allocate memory for the derived secret and copy
     * the x co-ordinate of pointQ into it.
     */
    SECITEM_AllocItem(NULL, derivedSecret, len);
    memcpy(derivedSecret->data, pointQ.data + 1, len);

    rv = SECSuccess;

#if EC_DEBUG
    printf("derived_secret:\n");
    for (i = 0; i < derivedSecret->len; i++) 
	printf("%02x:", derivedSecret->data[i]);
    printf("\n");
#endif

cleanup:
    mp_clear(&k);

    if (err) {
	MP_TO_SEC_ERROR(err);
    }

    if (pointQ.data) {
	PORT_ZFree(pointQ.data, 2*len + 1);
    }
#else
    PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
#endif /* NSS_ENABLE_ECC */

    return rv;
}