Beispiel #1
0
CERTAVA *
CERT_CopyAVA(PLArenaPool *arena, CERTAVA *from)
{
    CERTAVA *ava;
    int rv;

    ava = (CERTAVA *)PORT_ArenaZAlloc(arena, sizeof(CERTAVA));
    if (ava) {
        rv = SECITEM_CopyItem(arena, &ava->type, &from->type);
        if (rv)
            goto loser;
        rv = SECITEM_CopyItem(arena, &ava->value, &from->value);
        if (rv)
            goto loser;
    }
    return ava;

loser:
    return 0;
}
Beispiel #2
0
/*
 * NSS_CMSAttribute_Create - create an attribute
 *
 * if value is NULL, the attribute won't have a value. It can be added later
 * with NSS_CMSAttribute_AddValue.
 */
NSSCMSAttribute *
NSS_CMSAttribute_Create(PRArenaPool *poolp, SECOidTag oidtag, SECItem *value, PRBool encoded)
{
    NSSCMSAttribute *attr;
    SECItem *copiedvalue;
    void *mark;

    PORT_Assert (poolp != NULL);

    mark = PORT_ArenaMark (poolp);

    attr = (NSSCMSAttribute *)PORT_ArenaZAlloc(poolp, sizeof(NSSCMSAttribute));
    if (attr == NULL)
	goto loser;

    attr->typeTag = SECOID_FindOIDByTag(oidtag);
    if (attr->typeTag == NULL)
	goto loser;

    if (SECITEM_CopyItem(poolp, &(attr->type), &(attr->typeTag->oid)) != SECSuccess)
	goto loser;

    if (value != NULL) {
	if ((copiedvalue = SECITEM_ArenaDupItem(poolp, value)) == NULL)
	    goto loser;

	if (NSS_CMSArray_Add(poolp, (void ***)&(attr->values), (void *)copiedvalue) != SECSuccess)
	    goto loser;
    }

    attr->encoded = encoded;

    PORT_ArenaUnmark (poolp, mark);

    return attr;

loser:
    PORT_Assert (mark != NULL);
    PORT_ArenaRelease (poolp, mark);
    return NULL;
}
/* allocate space for a PFX structure and set up initial
 * arena pool.  pfx structure is cleared and a pointer to
 * the new structure is returned.
 */
SEC_PKCS12AuthenticatedSafe *
sec_pkcs12_new_asafe(PLArenaPool *poolp)
{
    SEC_PKCS12AuthenticatedSafe  *asafe = NULL;
    void *mark;

    mark = PORT_ArenaMark(poolp);
    asafe = (SEC_PKCS12AuthenticatedSafe *)PORT_ArenaZAlloc(poolp, 
	sizeof(SEC_PKCS12AuthenticatedSafe));
    if(asafe == NULL)
	goto loser;
    asafe->poolp = poolp;
    PORT_Memset(&asafe->old_baggage, 0, sizeof(SEC_PKCS7ContentInfo));

    PORT_ArenaUnmark(poolp, mark);
    return asafe;

loser:
    PORT_ArenaRelease(poolp, mark);
    return NULL;
}
/* allocate space for a PFX structure and set up initial
 * arena pool.  pfx structure is cleared and a pointer to
 * the new structure is returned.
 */
SEC_PKCS12PFXItem *
sec_pkcs12_new_pfx(void)
{
    SEC_PKCS12PFXItem   *pfx = NULL;
    PLArenaPool     *poolp = NULL;

    poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);	/* XXX Different size? */
    if(poolp == NULL)
	goto loser;

    pfx = (SEC_PKCS12PFXItem *)PORT_ArenaZAlloc(poolp, 
	sizeof(SEC_PKCS12PFXItem));
    if(pfx == NULL)
	goto loser;
    pfx->poolp = poolp;

    return pfx;

loser:
    PORT_FreeArena(poolp, PR_TRUE);
    return NULL;
}
/*
 * SecCmsMessageCreate - create a CMS message object
 *
 * "poolp" - arena to allocate memory from, or NULL if new arena should be created
 */
SecCmsMessageRef
SecCmsMessageCreate(void)
{
    PLArenaPool *poolp;
    SecCmsMessageRef cmsg;

    poolp = PORT_NewArena (1024);           /* XXX what is right value? */
    if (poolp == NULL)
	return NULL;

    cmsg = (SecCmsMessageRef)PORT_ArenaZAlloc (poolp, sizeof(SecCmsMessage));
    if (cmsg == NULL) {
	PORT_FreeArena(poolp, PR_FALSE);
	return NULL;
    }

    cmsg->poolp = poolp;
    cmsg->contentInfo.cmsg = cmsg;
    cmsg->refCount = 1;

    return cmsg;
}
Beispiel #6
0
/* compute the thumbprint of the DER cert and create a digest info
 * to store it in and return the digest info.
 * a return of NULL indicates an error.
 */
SGNDigestInfo *
sec_pkcs12_compute_thumbprint(SECItem *der_cert)
{
    SGNDigestInfo *thumb = NULL;
    SECItem digest;
    PRArenaPool *temparena = NULL;
    SECStatus rv = SECFailure;

    if(der_cert == NULL)
	return NULL;

    temparena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
    if(temparena == NULL) {
	return NULL;
    }

    digest.data = (unsigned char *)PORT_ArenaZAlloc(temparena,
						    sizeof(unsigned char) * 
						    SHA1_LENGTH);
    /* digest data and create digest info */
    if(digest.data != NULL) {
	digest.len = SHA1_LENGTH;
	rv = PK11_HashBuf(SEC_OID_SHA1, digest.data, der_cert->data, 
	                  der_cert->len);
	if(rv == SECSuccess) {
	    thumb = SGN_CreateDigestInfo(SEC_OID_SHA1, 
					 digest.data, 
					 digest.len);
	} else {
	    PORT_SetError(SEC_ERROR_NO_MEMORY);
	}
    } else {
	PORT_SetError(SEC_ERROR_NO_MEMORY);
    }

    PORT_FreeArena(temparena, PR_TRUE);

    return thumb;
}
/*
 * NSS_CMSMessage_Create - create a CMS message object
 *
 * "poolp" - arena to allocate memory from, or NULL if new arena should be created
 */
NSSCMSMessage *
NSS_CMSMessage_Create(PLArenaPool *poolp)
{
    void *mark = NULL;
    NSSCMSMessage *cmsg;
    PRBool poolp_is_ours = PR_FALSE;

    if (poolp == NULL) {
	poolp = PORT_NewArena (1024);           /* XXX what is right value? */
	if (poolp == NULL)
	    return NULL;
	poolp_is_ours = PR_TRUE;
    } 

    if (!poolp_is_ours)
	mark = PORT_ArenaMark(poolp);

    cmsg = (NSSCMSMessage *)PORT_ArenaZAlloc (poolp, sizeof(NSSCMSMessage));
    if (cmsg == NULL) {
	if (!poolp_is_ours) {
	    if (mark) {
		PORT_ArenaRelease(poolp, mark);
	    }
	} else
	    PORT_FreeArena(poolp, PR_FALSE);
	return NULL;
    }
    NSS_CMSContentInfo_Private_Init(&(cmsg->contentInfo));

    cmsg->poolp = poolp;
    cmsg->poolp_is_ours = poolp_is_ours;
    cmsg->refCount = 1;

    if (mark)
	PORT_ArenaUnmark(poolp, mark);

    return cmsg;
}
Beispiel #8
0
SECStatus
NSS_CMSSignedData_AddDigest(PLArenaPool *poolp,
                            NSSCMSSignedData *sigd,
                            SECOidTag digestalgtag,
                            SECItem *digest)
{
    SECAlgorithmID *digestalg;
    void *mark;

    if (!sigd || !poolp) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    mark = PORT_ArenaMark(poolp);

    digestalg = PORT_ArenaZAlloc(poolp, sizeof(SECAlgorithmID));
    if (digestalg == NULL)
        goto loser;

    if (SECOID_SetAlgorithmID(poolp, digestalg, digestalgtag, NULL) != SECSuccess) /* no params */
        goto loser;

    if (NSS_CMSArray_Add(poolp, (void ***)&(sigd->digestAlgorithms),
                         (void *)digestalg) != SECSuccess ||
        /* even if digest is NULL, add dummy to have same-size array */
        NSS_CMSArray_Add(poolp, (void ***)&(sigd->digests),
                         (void *)digest) != SECSuccess) {
        goto loser;
    }

    PORT_ArenaUnmark(poolp, mark);
    return SECSuccess;

loser:
    PORT_ArenaRelease(poolp, mark);
    return SECFailure;
}
Beispiel #9
0
static
CERTCertificate *createEmptyCertificate(void)
{
    PLArenaPool *arena = 0;
    CERTCertificate *c = 0;

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if ( !arena ) {
	return 0;
    }


    c = (CERTCertificate *) PORT_ArenaZAlloc(arena, sizeof(CERTCertificate));

    if (c) {
	c->referenceCount = 1;
	c->arena = arena;
    } else {
	PORT_FreeArena(arena,PR_TRUE);
    }

    return c;
}
Beispiel #10
0
CERTAVA *
CERT_CreateAVAFromSECItem(PRArenaPool *arena, SECOidTag kind, int valueType, 
                          SECItem *value)
{
    CERTAVA *ava;
    int rv;
    unsigned maxLen;

    ava = (CERTAVA*) PORT_ArenaZAlloc(arena, sizeof(CERTAVA));
    if (ava) {
	rv = SetupAVAType(arena, kind, &ava->type, &maxLen);
	if (rv) {
	    /* Illegal AVA type */
	    return NULL;
	}
	rv = SetupAVAValue(arena, valueType, value, &ava->value, maxLen);
	if (rv) {
	    /* Illegal value type */
	    return NULL;
	}
    }
    return ava;
}
static PQGParams *
decode_pqg_params(char *aStr)
{
    unsigned char *buf = nullptr;
    unsigned int len;
    PLArenaPool *arena = nullptr;
    PQGParams *params = nullptr;
    SECStatus status;

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (!arena)
        return nullptr;

    params = static_cast<PQGParams*>(PORT_ArenaZAlloc(arena, sizeof(PQGParams)));
    if (!params)
        goto loser;
    params->arena = arena;

    buf = ATOB_AsciiToData(aStr, &len);
    if ((!buf) || (len == 0))
        goto loser;

    status = SEC_ASN1Decode(arena, params, SECKEY_PQGParamsTemplate, (const char*)buf, len);
    if (status != SECSuccess)
        goto loser;

    return params;

loser:
    if (arena) {
      PORT_FreeArena(arena, false);
    }
    if (buf) {
      PR_Free(buf);
    }
    return nullptr;
}
static char *
nssutil_formatValue(PRArenaPool *arena, char *value, char quote)
{
    char *vp,*vp2,*retval;
    int size = 0, escapes = 0;

    for (vp=value; *vp ;vp++) {
	if ((*vp == quote) || (*vp == NSSUTIL_ARG_ESCAPE)) escapes++;
	size++;
    }
    if (arena) {
	retval = PORT_ArenaZAlloc(arena,size+escapes+1);
    } else {
	retval = PORT_ZAlloc(size+escapes+1);
    }
    if (retval == NULL) return NULL;
    vp2 = retval;
    for (vp=value; *vp; vp++) {
	if ((*vp == quote) || (*vp == NSSUTIL_ARG_ESCAPE)) 
				*vp2++ = NSSUTIL_ARG_ESCAPE;
	*vp2++ = *vp;
    }
    return retval;
}
Beispiel #13
0
static long
smime_choose_cipher(CERTCertificate *scert, CERTCertificate **rcerts)
{
    PLArenaPool *poolp;
    long chosen_cipher;
    int *cipher_abilities;
    int *cipher_votes;
    int strong_mapi;
    int rcount, mapi, max;

    if (smime_policy_bits == 0) {
        PORT_SetError(SEC_ERROR_BAD_EXPORT_ALGORITHM);
        return -1;
    }

    chosen_cipher = SMIME_RC2_CBC_40; /* the default, LCD */

    poolp = PORT_NewArena(1024); /* XXX what is right value? */
    if (poolp == NULL)
        goto done;

    cipher_abilities = (int *)PORT_ArenaZAlloc(poolp,
                                               smime_symmetric_count * sizeof(int));
    if (cipher_abilities == NULL)
        goto done;

    cipher_votes = (int *)PORT_ArenaZAlloc(poolp,
                                           smime_symmetric_count * sizeof(int));
    if (cipher_votes == NULL)
        goto done;

    /*
     * XXX Should have a #define somewhere which specifies default
     * strong cipher.  (Or better, a way to configure.)
     */

    /* Make triple-DES the strong cipher. */
    strong_mapi = smime_mapi_by_cipher(SMIME_DES_EDE3_168);

    PORT_Assert(strong_mapi >= 0);

    for (rcount = 0; rcerts[rcount] != NULL; rcount++) {
        SECItem *profile;
        smime_capability **caps;
        int capi, pref;
        SECStatus dstat;

        pref = smime_symmetric_count;
        profile = CERT_FindSMimeProfile(rcerts[rcount]);
        if (profile != NULL && profile->data != NULL && profile->len > 0) {
            caps = NULL;
            dstat = SEC_QuickDERDecodeItem(poolp, &caps,
                                           smime_capabilities_template,
                                           profile);
            if (dstat == SECSuccess && caps != NULL) {
                for (capi = 0; caps[capi] != NULL; capi++) {
                    smime_fill_capability(caps[capi]);
                    mapi = smime_mapi_by_cipher(caps[capi]->cipher);
                    if (mapi >= 0) {
                        cipher_abilities[mapi]++;
                        cipher_votes[mapi] += pref;
                        --pref;
                    }
                }
            }
        } else {
            SECKEYPublicKey *key;
            unsigned int pklen_bits;

            /*
             * XXX This is probably only good for RSA keys.  What I would
             * really like is a function to just say;  Is the public key in
             * this cert an export-length key?  Then I would not have to
             * know things like the value 512, or the kind of key, or what
             * a subjectPublicKeyInfo is, etc.
             */
            key = CERT_ExtractPublicKey(rcerts[rcount]);
            if (key != NULL) {
                pklen_bits = SECKEY_PublicKeyStrength(key) * 8;
                SECKEY_DestroyPublicKey(key);

                if (pklen_bits > 512) {
                    cipher_abilities[strong_mapi]++;
                    cipher_votes[strong_mapi] += pref;
                }
            }
        }
        if (profile != NULL)
            SECITEM_FreeItem(profile, PR_TRUE);
    }

    max = 0;
    for (mapi = 0; mapi < smime_symmetric_count; mapi++) {
        if (cipher_abilities[mapi] != rcount)
            continue;
        if (!smime_cipher_allowed(smime_cipher_maps[mapi].cipher))
            continue;
        if (cipher_votes[mapi] > max) {
            chosen_cipher = smime_cipher_maps[mapi].cipher;
            max = cipher_votes[mapi];
        } /* XXX else if a tie, let scert break it? */
    }

done:
    if (poolp != NULL)
        PORT_FreeArena(poolp, PR_FALSE);

    return chosen_cipher;
}
Beispiel #14
0
NSSCMSRecipientInfo *
nss_cmsrecipientinfo_create(NSSCMSMessage *cmsg, 
			    NSSCMSRecipientIDSelector type,
                            CERTCertificate *cert, 
			    SECKEYPublicKey *pubKey, 
                            SECItem *subjKeyID, 
			    void* pwfn_arg, 
			    SECItem* DERinput)
{
    NSSCMSRecipientInfo *ri;
    void *mark;
    SECOidTag certalgtag;
    SECStatus rv = SECSuccess;
    NSSCMSRecipientEncryptedKey *rek;
    NSSCMSOriginatorIdentifierOrKey *oiok;
    unsigned long version;
    SECItem *dummy;
    PLArenaPool *poolp;
    CERTSubjectPublicKeyInfo *spki, *freeSpki = NULL;
    NSSCMSRecipientIdentifier *rid;
    extern const SEC_ASN1Template NSSCMSRecipientInfoTemplate[];

    if (!cmsg) {
	/* a CMSMessage wasn't supplied, create a fake one to hold the pwfunc
	 * and a private arena pool */
	cmsg = NSS_CMSMessage_Create(NULL);
        cmsg->pwfn_arg = pwfn_arg;
	/* mark it as a special cms message */
	cmsg->contentInfo.contentTypeTag = (SECOidData *)&fakeContent;
    }

    poolp = cmsg->poolp;

    mark = PORT_ArenaMark(poolp);

    ri = (NSSCMSRecipientInfo *)PORT_ArenaZAlloc(poolp, sizeof(NSSCMSRecipientInfo));
    if (ri == NULL)
	goto loser;

    ri->cmsg = cmsg;

    if (DERinput) {
        /* decode everything from DER */
        SECItem newinput;
        SECStatus rv = SECITEM_CopyItem(poolp, &newinput, DERinput);
        if (SECSuccess != rv)
            goto loser;
        rv = SEC_QuickDERDecodeItem(poolp, ri, NSSCMSRecipientInfoTemplate, &newinput);
        if (SECSuccess != rv)
            goto loser;
    }

    switch (type) {
        case NSSCMSRecipientID_IssuerSN:
        {
            ri->cert = CERT_DupCertificate(cert);
            if (NULL == ri->cert)
                goto loser;
            spki = &(cert->subjectPublicKeyInfo);
            break;
        }
        
        case NSSCMSRecipientID_SubjectKeyID:
        {
            PORT_Assert(pubKey);
            spki = freeSpki = SECKEY_CreateSubjectPublicKeyInfo(pubKey);
            break;
        }

	case NSSCMSRecipientID_BrandNew:
	    goto done;
	    break;

        default:
            /* unkown type */
            goto loser;
            break;
    }

    certalgtag = SECOID_GetAlgorithmTag(&(spki->algorithm));

    rid = &ri->ri.keyTransRecipientInfo.recipientIdentifier;
    switch (certalgtag) {
    case SEC_OID_PKCS1_RSA_ENCRYPTION:
	ri->recipientInfoType = NSSCMSRecipientInfoID_KeyTrans;
	rid->identifierType = type;
	if (type == NSSCMSRecipientID_IssuerSN) {
	    rid->id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert);
	    if (rid->id.issuerAndSN == NULL) {
	      break;
	    }
	} else if (type == NSSCMSRecipientID_SubjectKeyID){
	    NSSCMSKeyTransRecipientInfoEx *riExtra;

	    rid->id.subjectKeyID = PORT_ArenaNew(poolp, SECItem);
	    if (rid->id.subjectKeyID == NULL) {
		rv = SECFailure;
		PORT_SetError(SEC_ERROR_NO_MEMORY);
		break;
	    } 
	    SECITEM_CopyItem(poolp, rid->id.subjectKeyID, subjKeyID);
	    if (rid->id.subjectKeyID->data == NULL) {
		rv = SECFailure;
		PORT_SetError(SEC_ERROR_NO_MEMORY);
		break;
	    }
	    riExtra = &ri->ri.keyTransRecipientInfoEx;
	    riExtra->version = 0;
	    riExtra->pubKey = SECKEY_CopyPublicKey(pubKey);
	    if (riExtra->pubKey == NULL) {
		rv = SECFailure;
		PORT_SetError(SEC_ERROR_NO_MEMORY);
		break;
	    }
	} else {
	    PORT_SetError(SEC_ERROR_INVALID_ARGS);
	    rv = SECFailure;
	}
	break;
    case SEC_OID_X942_DIFFIE_HELMAN_KEY: /* dh-public-number */
	PORT_Assert(type == NSSCMSRecipientID_IssuerSN);
	if (type != NSSCMSRecipientID_IssuerSN) {
	    rv = SECFailure;
	    break;
	}
	/* a key agreement op */
	ri->recipientInfoType = NSSCMSRecipientInfoID_KeyAgree;

	if (ri->ri.keyTransRecipientInfo.recipientIdentifier.id.issuerAndSN == NULL) {
	    rv = SECFailure;
	    break;
	}
	/* we do not support the case where multiple recipients 
	 * share the same KeyAgreeRecipientInfo and have multiple RecipientEncryptedKeys
	 * in this case, we would need to walk all the recipientInfos, take the
	 * ones that do KeyAgreement algorithms and join them, algorithm by algorithm
	 * Then, we'd generate ONE ukm and OriginatorIdentifierOrKey */

	/* only epheremal-static Diffie-Hellman is supported for now
	 * this is the only form of key agreement that provides potential anonymity
	 * of the sender, plus we do not have to include certs in the message */

	/* force single recipientEncryptedKey for now */
	if ((rek = NSS_CMSRecipientEncryptedKey_Create(poolp)) == NULL) {
	    rv = SECFailure;
	    break;
	}

	/* hardcoded IssuerSN choice for now */
	rek->recipientIdentifier.identifierType = NSSCMSKeyAgreeRecipientID_IssuerSN;
	if ((rek->recipientIdentifier.id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert)) == NULL) {
	    rv = SECFailure;
	    break;
	}

	oiok = &(ri->ri.keyAgreeRecipientInfo.originatorIdentifierOrKey);

	/* see RFC2630 12.3.1.1 */
	oiok->identifierType = NSSCMSOriginatorIDOrKey_OriginatorPublicKey;

	rv = NSS_CMSArray_Add(poolp, (void ***)&ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys,
				    (void *)rek);

	break;
    default:
	/* other algorithms not supported yet */
	/* NOTE that we do not support any KEK algorithm */
	PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
	rv = SECFailure;
	break;
    }

    if (rv == SECFailure)
	goto loser;

    /* set version */
    switch (ri->recipientInfoType) {
    case NSSCMSRecipientInfoID_KeyTrans:
	if (ri->ri.keyTransRecipientInfo.recipientIdentifier.identifierType == NSSCMSRecipientID_IssuerSN)
	    version = NSS_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_ISSUERSN;
	else
	    version = NSS_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_SUBJKEY;
	dummy = SEC_ASN1EncodeInteger(poolp, &(ri->ri.keyTransRecipientInfo.version), version);
	if (dummy == NULL)
	    goto loser;
	break;
    case NSSCMSRecipientInfoID_KeyAgree:
	dummy = SEC_ASN1EncodeInteger(poolp, &(ri->ri.keyAgreeRecipientInfo.version),
						NSS_CMS_KEYAGREE_RECIPIENT_INFO_VERSION);
	if (dummy == NULL)
	    goto loser;
	break;
    case NSSCMSRecipientInfoID_KEK:
	/* NOTE: this cannot happen as long as we do not support any KEK algorithm */
	dummy = SEC_ASN1EncodeInteger(poolp, &(ri->ri.kekRecipientInfo.version),
						NSS_CMS_KEK_RECIPIENT_INFO_VERSION);
	if (dummy == NULL)
	    goto loser;
	break;
    
    }

done:
    PORT_ArenaUnmark (poolp, mark);
    if (freeSpki)
      SECKEY_DestroySubjectPublicKeyInfo(freeSpki);
    return ri;

loser:
    if (ri && ri->cert) {
        CERT_DestroyCertificate(ri->cert);
    }
    if (freeSpki) {
      SECKEY_DestroySubjectPublicKeyInfo(freeSpki);
    }
    PORT_ArenaRelease (poolp, mark);
    if (cmsg->contentInfo.contentTypeTag == &fakeContent) {
	NSS_CMSMessage_Destroy(cmsg);
    }
    return NULL;
}
static int
sm_encrypt(CamelCipherContext *context, const char *userid, GPtrArray *recipients, CamelMimePart *ipart, CamelMimePart *opart, CamelException *ex)
{
	struct _CamelSMIMEContextPrivate *p = ((CamelSMIMEContext *)context)->priv;
	/*NSSCMSRecipientInfo **recipient_infos;*/
	CERTCertificate **recipient_certs = NULL;
	NSSCMSContentInfo *cinfo;
	PK11SymKey *bulkkey = NULL;
	SECOidTag bulkalgtag;
	int bulkkeysize, i;
	CK_MECHANISM_TYPE type;
	PK11SlotInfo *slot;
	PLArenaPool *poolp;
	NSSCMSMessage *cmsg = NULL;
	NSSCMSEnvelopedData *envd;
 	NSSCMSEncoderContext *enc = NULL;
	CamelStreamMem *mem;
	CamelStream *ostream = NULL;
	CamelDataWrapper *dw;
	CamelContentType *ct;

	poolp = PORT_NewArena(1024);
	if (poolp == NULL) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, g_strerror (ENOMEM));
		return -1;
	}

	/* Lookup all recipients certs, for later working */
	recipient_certs = (CERTCertificate **)PORT_ArenaZAlloc(poolp, sizeof(*recipient_certs[0])*(recipients->len + 1));
	if (recipient_certs == NULL) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, g_strerror (ENOMEM));
		goto fail;
	}

	for (i=0;i<recipients->len;i++) {
		recipient_certs[i] = CERT_FindCertByNicknameOrEmailAddr(p->certdb, recipients->pdata[i]);
		if (recipient_certs[i] == NULL) {
			camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot find certificate for `%s'"), recipients->pdata[i]);
			goto fail;
		}
	}

	/* Find a common algorithm, probably 3DES anyway ... */
	if (NSS_SMIMEUtil_FindBulkAlgForRecipients(recipient_certs, &bulkalgtag, &bulkkeysize) != SECSuccess) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot find common bulk encryption algorithm"));
		goto fail;
	}

	/* Generate a new bulk key based on the common algorithm - expensive */
	type = PK11_AlgtagToMechanism(bulkalgtag);
	slot = PK11_GetBestSlot(type, context);
	if (slot == NULL) {
		/* PORT_GetError(); ?? */
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot allocate slot for encryption bulk key"));
		goto fail;
	}

	bulkkey = PK11_KeyGen(slot, type, NULL, bulkkeysize/8, context);
	PK11_FreeSlot(slot);

	/* Now we can start building the message */
	/* msg->envelopedData->data */
	cmsg = NSS_CMSMessage_Create(NULL);
	if (cmsg == NULL) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create CMS Message"));
		goto fail;
	}

	envd = NSS_CMSEnvelopedData_Create(cmsg, bulkalgtag, bulkkeysize);
	if (envd == NULL) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create CMS Enveloped data"));
		goto fail;
	}

	cinfo = NSS_CMSMessage_GetContentInfo(cmsg);
	if (NSS_CMSContentInfo_SetContent_EnvelopedData(cmsg, cinfo, envd) != SECSuccess) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot attach CMS Enveloped data"));
		goto fail;
	}

	cinfo = NSS_CMSEnvelopedData_GetContentInfo(envd);
	if (NSS_CMSContentInfo_SetContent_Data(cmsg, cinfo, NULL, PR_FALSE) != SECSuccess) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot attach CMS data object"));
		goto fail;
	}

	/* add recipient certs */
	for (i=0;recipient_certs[i];i++) {
		NSSCMSRecipientInfo *ri = NSS_CMSRecipientInfo_Create(cmsg, recipient_certs[i]);

		if (ri == NULL) {
			camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create CMS Recipient information"));
			goto fail;
		}

		if (NSS_CMSEnvelopedData_AddRecipient(envd, ri) != SECSuccess) {
			camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot add CMS Recipient information"));
			goto fail;
		}
	}

	/* dump it out */
	ostream = camel_stream_mem_new();
	enc = NSS_CMSEncoder_Start(cmsg,
				   sm_write_stream, ostream,
				   NULL, NULL,
				   NULL, NULL,
				   sm_decrypt_key, bulkkey,
				   NULL, NULL);
	if (enc == NULL) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create encoder context"));
		goto fail;
	}

	/* FIXME: Stream the input */
	/* FIXME: Canonicalise the input? */
	mem = (CamelStreamMem *)camel_stream_mem_new();
	camel_data_wrapper_write_to_stream((CamelDataWrapper *)ipart, (CamelStream *)mem);
	if (NSS_CMSEncoder_Update(enc, (char *) mem->buffer->data, mem->buffer->len) != SECSuccess) {
		NSS_CMSEncoder_Cancel(enc);
		camel_object_unref(mem);
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to add data to encoder"));
		goto fail;
	}
	camel_object_unref(mem);

	if (NSS_CMSEncoder_Finish(enc) != SECSuccess) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to encode data"));
		goto fail;
	}

	PK11_FreeSymKey(bulkkey);
	NSS_CMSMessage_Destroy(cmsg);
	for (i=0;recipient_certs[i];i++)
		CERT_DestroyCertificate(recipient_certs[i]);
	PORT_FreeArena(poolp, PR_FALSE);

	dw = camel_data_wrapper_new();
	camel_data_wrapper_construct_from_stream(dw, ostream);
	camel_object_unref(ostream);
	dw->encoding = CAMEL_TRANSFER_ENCODING_BINARY;

	ct = camel_content_type_new("application", "x-pkcs7-mime");
	camel_content_type_set_param(ct, "name", "smime.p7m");
	camel_content_type_set_param(ct, "smime-type", "enveloped-data");
	camel_data_wrapper_set_mime_type_field(dw, ct);
	camel_content_type_unref(ct);

	camel_medium_set_content_object((CamelMedium *)opart, dw);
	camel_object_unref(dw);

	camel_mime_part_set_disposition(opart, "attachment");
	camel_mime_part_set_filename(opart, "smime.p7m");
	camel_mime_part_set_description(opart, "S/MIME Encrypted Message");
	camel_mime_part_set_encoding(opart, CAMEL_TRANSFER_ENCODING_BASE64);

	return 0;

fail:
	if (ostream)
		camel_object_unref(ostream);
	if (cmsg)
		NSS_CMSMessage_Destroy(cmsg);
	if (bulkkey)
		PK11_FreeSymKey(bulkkey);

	if (recipient_certs) {
		for (i=0;recipient_certs[i];i++)
			CERT_DestroyCertificate(recipient_certs[i]);
	}

	PORT_FreeArena(poolp, PR_FALSE);

	return -1;
}
/*
 * SecCmsDigestContextFinishMultiple - finish the digests and put them
 *  into an array of CSSM_DATAs (allocated on poolp)
 */
OSStatus
SecCmsDigestContextFinishMultiple(SecCmsDigestContextRef cmsdigcx, SecArenaPoolRef poolp,
			    CSSM_DATA_PTR **digestsp)
{
    CSSM_CC_HANDLE digobj;
    CSSM_DATA_PTR *digests, digest;
    int i;
    void *mark;
    OSStatus rv = SECFailure;

    /* no contents? do not update digests */
    if (digestsp == NULL || !cmsdigcx->saw_contents) {
	for (i = 0; i < cmsdigcx->digcnt; i++)
	    if (cmsdigcx->digobjs[i])
		CSSM_DeleteContext(cmsdigcx->digobjs[i]);
	rv = SECSuccess;
	if (digestsp)
	    *digestsp = NULL;
	goto cleanup;
    }

    mark = PORT_ArenaMark ((PLArenaPool *)poolp);

    /* allocate digest array & CSSM_DATAs on arena */
    digests = (CSSM_DATA_PTR *)PORT_ArenaAlloc((PLArenaPool *)poolp, (cmsdigcx->digcnt+1) * sizeof(CSSM_DATA_PTR));
    digest = (CSSM_DATA_PTR)PORT_ArenaZAlloc((PLArenaPool *)poolp, cmsdigcx->digcnt * sizeof(CSSM_DATA));
    if (digests == NULL || digest == NULL) {
	goto loser;
    }

    for (i = 0; i < cmsdigcx->digcnt; i++, digest++) {
	digobj = cmsdigcx->digobjs[i];
	CSSM_QUERY_SIZE_DATA dataSize;
	rv = CSSM_QuerySize(digobj, CSSM_FALSE, 1, &dataSize);
        if (rv != CSSM_OK)
        {
            goto loser;
        }
        
	int diglength = dataSize.SizeOutputBlock;
	
	if (digobj)
	{
	    digest->Data = (unsigned char*)PORT_ArenaAlloc((PLArenaPool *)poolp, diglength);
	    if (digest->Data == NULL)
		goto loser;
	    digest->Length = diglength;
	    rv = CSSM_DigestDataFinal(digobj, digest);
            if (rv != CSSM_OK)
            {
                goto loser;
            }
            
	    CSSM_DeleteContext(digobj);
	}
	else
	{
	    digest->Data = NULL;
	    digest->Length = 0;
	}
	
	digests[i] = digest;
   }
    digests[i] = NULL;
    *digestsp = digests;

    rv = SECSuccess;

loser:
    if (rv == SECSuccess)
	PORT_ArenaUnmark((PLArenaPool *)poolp, mark);
    else
	PORT_ArenaRelease((PLArenaPool *)poolp, mark);

cleanup:
    if (cmsdigcx->digcnt > 0) {
	PORT_Free(cmsdigcx->digobjs);
    }
    PORT_Free(cmsdigcx);

    return rv;
}
Beispiel #17
0
NSSLOWKEYPublicKey *
nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
{
    NSSLOWKEYPublicKey *pubk;
    PLArenaPool *arena;


    arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
    if (arena == NULL) {
        PORT_SetError (SEC_ERROR_NO_MEMORY);
        return NULL;
    }

    switch(privk->keyType) {
      case NSSLOWKEYRSAKey:
      case NSSLOWKEYNullKey:
	pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
						sizeof (NSSLOWKEYPublicKey));
	if (pubk != NULL) {
	    SECStatus rv;

	    pubk->arena = arena;
	    pubk->keyType = privk->keyType;
	    if (privk->keyType == NSSLOWKEYNullKey) return pubk;
	    rv = SECITEM_CopyItem(arena, &pubk->u.rsa.modulus,
				  &privk->u.rsa.modulus);
	    if (rv == SECSuccess) {
		rv = SECITEM_CopyItem (arena, &pubk->u.rsa.publicExponent,
				       &privk->u.rsa.publicExponent);
		if (rv == SECSuccess)
		    return pubk;
	    }
	} else {
	    PORT_SetError (SEC_ERROR_NO_MEMORY);
	}
	break;
      case NSSLOWKEYDSAKey:
	pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
						    sizeof(NSSLOWKEYPublicKey));
	if (pubk != NULL) {
	    SECStatus rv;

	    pubk->arena = arena;
	    pubk->keyType = privk->keyType;
	    rv = SECITEM_CopyItem(arena, &pubk->u.dsa.publicValue,
				  &privk->u.dsa.publicValue);
	    if (rv != SECSuccess) break;
	    rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime,
				  &privk->u.dsa.params.prime);
	    if (rv != SECSuccess) break;
	    rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime,
				  &privk->u.dsa.params.subPrime);
	    if (rv != SECSuccess) break;
	    rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base,
				  &privk->u.dsa.params.base);
	    if (rv == SECSuccess) return pubk;
	}
	break;
      case NSSLOWKEYDHKey:
	pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
						    sizeof(NSSLOWKEYPublicKey));
	if (pubk != NULL) {
	    SECStatus rv;

	    pubk->arena = arena;
	    pubk->keyType = privk->keyType;
	    rv = SECITEM_CopyItem(arena, &pubk->u.dh.publicValue,
				  &privk->u.dh.publicValue);
	    if (rv != SECSuccess) break;
	    rv = SECITEM_CopyItem(arena, &pubk->u.dh.prime,
				  &privk->u.dh.prime);
	    if (rv != SECSuccess) break;
	    rv = SECITEM_CopyItem(arena, &pubk->u.dh.base,
				  &privk->u.dh.base);
	    if (rv == SECSuccess) return pubk;
	}
	break;
#ifndef NSS_DISABLE_ECC
      case NSSLOWKEYECKey:
	pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
						    sizeof(NSSLOWKEYPublicKey));
	if (pubk != NULL) {
	    SECStatus rv;

	    pubk->arena = arena;
	    pubk->keyType = privk->keyType;
	    rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue,
				  &privk->u.ec.publicValue);
	    if (rv != SECSuccess) break;
	    pubk->u.ec.ecParams.arena = arena;
	    /* Copy the rest of the params */
	    rv = EC_CopyParams(arena, &(pubk->u.ec.ecParams),
			       &(privk->u.ec.ecParams));
	    if (rv == SECSuccess) return pubk;
	}
	break;
#endif /* NSS_DISABLE_ECC */
	/* No Fortezza in Low Key implementations (Fortezza keys aren't
	 * stored in our data base */
    default:
	break;
    }

    PORT_FreeArena (arena, PR_FALSE);
    return NULL;
}
Beispiel #18
0
SECStatus 
DH_GenParam(int primeLen, DHParams **params)
{
    PLArenaPool *arena;
    DHParams *dhparams;
    unsigned char *pb = NULL;
    unsigned char *ab = NULL;
    unsigned long counter = 0;
    mp_int p, q, a, h, psub1, test;
    mp_err err = MP_OKAY;
    SECStatus rv = SECSuccess;
    if (!params || primeLen < 0) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    }
    arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
    if (!arena) {
	PORT_SetError(SEC_ERROR_NO_MEMORY);
	return SECFailure;
    }
    dhparams = (DHParams *)PORT_ArenaZAlloc(arena, sizeof(DHParams));
    if (!dhparams) {
	PORT_SetError(SEC_ERROR_NO_MEMORY);
	PORT_FreeArena(arena, PR_TRUE);
	return SECFailure;
    }
    dhparams->arena = arena;
    MP_DIGITS(&p) = 0;
    MP_DIGITS(&q) = 0;
    MP_DIGITS(&a) = 0;
    MP_DIGITS(&h) = 0;
    MP_DIGITS(&psub1) = 0;
    MP_DIGITS(&test) = 0;
    CHECK_MPI_OK( mp_init(&p) );
    CHECK_MPI_OK( mp_init(&q) );
    CHECK_MPI_OK( mp_init(&a) );
    CHECK_MPI_OK( mp_init(&h) );
    CHECK_MPI_OK( mp_init(&psub1) );
    CHECK_MPI_OK( mp_init(&test) );
    /* generate prime with MPI, uses Miller-Rabin to generate strong prime. */
    pb = PORT_Alloc(primeLen);
    CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(pb, primeLen) );
    pb[0]          |= 0x80; /* set high-order bit */
    pb[primeLen-1] |= 0x01; /* set low-order bit  */
    CHECK_MPI_OK( mp_read_unsigned_octets(&p, pb, primeLen) );
    CHECK_MPI_OK( mpp_make_prime(&p, primeLen * 8, PR_TRUE, &counter) );
    /* construct Sophie-Germain prime q = (p-1)/2. */
    CHECK_MPI_OK( mp_sub_d(&p, 1, &psub1) );
    CHECK_MPI_OK( mp_div_2(&psub1, &q)    );
    /* construct a generator from the prime. */
    ab = PORT_Alloc(primeLen);
    /* generate a candidate number a in p's field */
    CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(ab, primeLen) );
    CHECK_MPI_OK( mp_read_unsigned_octets(&a, ab, primeLen) );
    /* force a < p (note that quot(a/p) <= 1) */
    if ( mp_cmp(&a, &p) > 0 )
	CHECK_MPI_OK( mp_sub(&a, &p, &a) );
    do {
	/* check that a is in the range [2..p-1] */
	if ( mp_cmp_d(&a, 2) < 0 || mp_cmp(&a, &psub1) >= 0) {
	    /* a is outside of the allowed range.  Set a=3 and keep going. */
            mp_set(&a, 3);
	}
	/* if a**q mod p != 1 then a is a generator */
	CHECK_MPI_OK( mp_exptmod(&a, &q, &p, &test) );
	if ( mp_cmp_d(&test, 1) != 0 )
	    break;
	/* increment the candidate and try again. */
	CHECK_MPI_OK( mp_add_d(&a, 1, &a) );
    } while (PR_TRUE);
    MPINT_TO_SECITEM(&p, &dhparams->prime, arena);
    MPINT_TO_SECITEM(&a, &dhparams->base, arena);
    *params = dhparams;
cleanup:
    mp_clear(&p);
    mp_clear(&q);
    mp_clear(&a);
    mp_clear(&h);
    mp_clear(&psub1);
    mp_clear(&test);
    if (pb) PORT_ZFree(pb, primeLen);
    if (ab) PORT_ZFree(ab, primeLen);
    if (err) {
	MP_TO_SEC_ERROR(err);
	rv = SECFailure;
    }
    if (rv)
	PORT_FreeArena(arena, PR_TRUE);
    return rv;
}
Beispiel #19
0
static void ListCRLNames (CERTCertDBHandle *certHandle, int crlType, PRBool deletecrls)
{
    CERTCrlHeadNode *crlList = NULL;
    CERTCrlNode *crlNode = NULL;
    CERTName *name = NULL;
    PLArenaPool *arena = NULL;
    SECStatus rv;

    do {
	arena = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE);
	if (arena == NULL) {
	    fprintf(stderr, "%s: fail to allocate memory\n", progName);
	    break;
	}
	
	name = PORT_ArenaZAlloc (arena, sizeof(*name));
	if (name == NULL) {
	    fprintf(stderr, "%s: fail to allocate memory\n", progName);
	    break;
	}
	name->arena = arena;
	    
	rv = SEC_LookupCrls (certHandle, &crlList, crlType);
	if (rv != SECSuccess) {
	    fprintf(stderr, "%s: fail to look up CRLs (%s)\n", progName,
	    SECU_Strerror(PORT_GetError()));
	    break;
	}
	
	/* just in case */
	if (!crlList)
	    break;

	crlNode  = crlList->first;

        fprintf (stdout, "\n");
	fprintf (stdout, "\n%-40s %-5s\n\n", "CRL names", "CRL Type");
	while (crlNode) {
	    char* asciiname = NULL;
	    CERTCertificate *cert = NULL;
	    if (crlNode->crl && &crlNode->crl->crl.derName) {
	        cert = CERT_FindCertByName(certHandle,
	                                   &crlNode->crl->crl.derName);
	        if (!cert) {
	            SECU_PrintError(progName, "could not find signing "
	                         "certificate in database");
	        }
	    }
	    if (cert) {
	        char* certName = NULL;
                 if (cert->nickname && PORT_Strlen(cert->nickname) > 0) {
	            certName = cert->nickname;
	        } else if (cert->emailAddr && PORT_Strlen(cert->emailAddr) > 0) {
	            certName = cert->emailAddr;
	        }
	        if (certName) {
	            asciiname = PORT_Strdup(certName);
	        }
	        CERT_DestroyCertificate(cert);
	    }
                
	    if (!asciiname) {
	        name = &crlNode->crl->crl.name;
	        if (!name){
	            SECU_PrintError(progName, "fail to get the CRL "
	                           "issuer name");
	            continue;
	        }
	        asciiname = CERT_NameToAscii(name);
	    }
	    fprintf (stdout, "%-40s %-5s\n", asciiname, "CRL");
	    if (asciiname) {
		PORT_Free(asciiname);
	    }
            if ( PR_TRUE == deletecrls) {
                CERTSignedCrl* acrl = NULL;
                SECItem* issuer = &crlNode->crl->crl.derName;
                acrl = SEC_FindCrlByName(certHandle, issuer, crlType);
                if (acrl)
                {
                    SEC_DeletePermCRL(acrl);
                    SEC_DestroyCrl(acrl);
                }
            }
            crlNode = crlNode->next;
	} 
	
    } while (0);
    if (crlList)
	PORT_FreeArena (crlList->arena, PR_FALSE);
    PORT_FreeArena (arena, PR_FALSE);
}
Beispiel #20
0
err_t RSA_signature_verify_nss(const struct RSA_public_key *k
                              , const u_char *hash_val, size_t hash_len
                               ,const u_char *sig_val, size_t sig_len)
{
   SECKEYPublicKey *publicKey;
   PRArenaPool *arena;
   SECStatus retVal = SECSuccess;
   SECItem nss_n, nss_e;
   SECItem signature, data;
   chunk_t n,e;

    /*Converting n and e to form public key in SECKEYPublicKey data structure*/

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (arena == NULL) {
	PORT_SetError (SEC_ERROR_NO_MEMORY);
	return "10" "NSS error: Not enough memory to create arena";
    }

    publicKey = (SECKEYPublicKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPublicKey));
    if (!publicKey) {
	PORT_FreeArena (arena, PR_FALSE);
	PORT_SetError (SEC_ERROR_NO_MEMORY);
	return "11" "NSS error: Not enough memory to create publicKey";
    }

    publicKey->arena = arena;
    publicKey->keyType = rsaKey;
    publicKey->pkcs11Slot = NULL;
    publicKey->pkcs11ID = CK_INVALID_HANDLE;

    /* Converting n(modulus) and e(exponent) from mpz_t form to chunk_t */
    n = mpz_to_n_autosize(&k->n);
    e = mpz_to_n_autosize(&k->e);

    /*Converting n and e to nss_n and nss_e*/
    nss_n.data = n.ptr;
    nss_n.len = (unsigned int)n.len;
    nss_n.type = siBuffer;

    nss_e.data = e.ptr;
    nss_e.len = (unsigned int)e.len;
    nss_e.type = siBuffer;

    retVal = SECITEM_CopyItem(arena, &publicKey->u.rsa.modulus, &nss_n);
    if (retVal == SECSuccess) {
	retVal = SECITEM_CopyItem (arena, &publicKey->u.rsa.publicExponent, &nss_e);
    }

    if(retVal != SECSuccess) {
	pfree(n.ptr);
	pfree(e.ptr);
	SECKEY_DestroyPublicKey (publicKey);
	return "12" "NSS error: Not able to copy modulus or exponent or both while forming SECKEYPublicKey structure";
    }
    signature.type = siBuffer;
    signature.data = DISCARD_CONST(unsigned char *, sig_val);
    signature.len  = (unsigned int)sig_len;

    data.len = (unsigned int)sig_len;
    data.data = alloc_bytes(data.len, "NSS decrypted signature");
    data.type = siBuffer;

    if(PK11_VerifyRecover(publicKey, &signature, &data, osw_return_nss_password_file_info()) == SECSuccess ) {
	DBG(DBG_CRYPT,DBG_dump("NSS RSA verify: decrypted sig: ", data.data, data.len));
    }
    else {
        DBG(DBG_CRYPT,DBG_log("NSS RSA verify: decrypting signature is failed"));
        return "13" "NSS error: Not able to decrypt";
    }

    if(memcmp(data.data+data.len-hash_len, hash_val, hash_len)!=0) {
	pfree(data.data);
	loglog(RC_LOG_SERIOUS, "RSA Signature NOT verified");
	return "14" "NSS error: Not able to verify";
    }

    DBG(DBG_CRYPT,DBG_dump("NSS RSA verify: hash value: ", hash_val, hash_len));

    pfree(data.data);
    pfree(n.ptr);
    pfree(e.ptr);
    SECKEY_DestroyPublicKey (publicKey);

    DBG(DBG_CRYPT, DBG_log("RSA Signature verified"));

    return NULL;
}
/* create a new external bag which is appended onto the list
 * of bags in baggage.  the bag is created in the same arena
 * as baggage
 */
SEC_PKCS12BaggageItem *
sec_pkcs12_create_external_bag(SEC_PKCS12Baggage *luggage)
{
    void *dummy, *mark;
    SEC_PKCS12BaggageItem *bag;

    if(luggage == NULL) {
	return NULL;
    }

    mark = PORT_ArenaMark(luggage->poolp);

    /* allocate space for null terminated bag list */
    if(luggage->bags == NULL) {
	luggage->bags=(SEC_PKCS12BaggageItem**)PORT_ArenaZAlloc(luggage->poolp, 
					sizeof(SEC_PKCS12BaggageItem *));
	if(luggage->bags == NULL) {
	    goto loser;
	}
	luggage->luggage_size = 0;
    }

    /* grow the list */    
    dummy = PORT_ArenaGrow(luggage->poolp, luggage->bags,
    			sizeof(SEC_PKCS12BaggageItem *) * (luggage->luggage_size + 1),
    			sizeof(SEC_PKCS12BaggageItem *) * (luggage->luggage_size + 2));
    if(dummy == NULL) {
	goto loser;
    }
    luggage->bags = (SEC_PKCS12BaggageItem**)dummy;

    luggage->bags[luggage->luggage_size] = 
    		(SEC_PKCS12BaggageItem *)PORT_ArenaZAlloc(luggage->poolp,
    							sizeof(SEC_PKCS12BaggageItem));
    if(luggage->bags[luggage->luggage_size] == NULL) {
	goto loser;
    }

    /* create new bag and append it to the end */
    bag = luggage->bags[luggage->luggage_size];
    bag->espvks = (SEC_PKCS12ESPVKItem **)PORT_ArenaZAlloc(
    						luggage->poolp,
    						sizeof(SEC_PKCS12ESPVKItem *));
    bag->unencSecrets = (SEC_PKCS12SafeBag **)PORT_ArenaZAlloc(
    						luggage->poolp,
    						sizeof(SEC_PKCS12SafeBag *));
    if((bag->espvks == NULL) || (bag->unencSecrets == NULL)) {
	goto loser;
    }

    bag->poolp = luggage->poolp;
    luggage->luggage_size++;
    luggage->bags[luggage->luggage_size] = NULL;
    bag->espvks[0] = NULL;
    bag->unencSecrets[0] = NULL;
    bag->nEspvks = bag->nSecrets = 0;

    PORT_ArenaUnmark(luggage->poolp, mark);
    return bag;

loser:
    PORT_ArenaRelease(luggage->poolp, mark);
    PORT_SetError(SEC_ERROR_NO_MEMORY);
    return NULL;
}
Beispiel #22
0
/*
 * smime_choose_cipher - choose a cipher that works for all the recipients
 *
 * "scert"  - sender's certificate
 * "rcerts" - recipient's certificates
 */
static long
smime_choose_cipher(CERTCertificate *scert, CERTCertificate **rcerts)
{
    PLArenaPool *poolp;
    long cipher;
    long chosen_cipher;
    int *cipher_abilities;
    int *cipher_votes;
    int weak_mapi;
    int strong_mapi;
    int aes128_mapi;
    int aes256_mapi;
    int rcount, mapi, max, i;

    chosen_cipher = SMIME_RC2_CBC_40;		/* the default, LCD */
    weak_mapi = smime_mapi_by_cipher(chosen_cipher);
    aes128_mapi = smime_mapi_by_cipher(SMIME_AES_CBC_128);
    aes256_mapi = smime_mapi_by_cipher(SMIME_AES_CBC_256);

    poolp = PORT_NewArena (1024);		/* XXX what is right value? */
    if (poolp == NULL)
	goto done;

    cipher_abilities = (int *)PORT_ArenaZAlloc(poolp, smime_cipher_map_count * sizeof(int));
    cipher_votes     = (int *)PORT_ArenaZAlloc(poolp, smime_cipher_map_count * sizeof(int));
    if (cipher_votes == NULL || cipher_abilities == NULL)
	goto done;

    /* Make triple-DES the strong cipher. */
    strong_mapi = smime_mapi_by_cipher (SMIME_DES_EDE3_168);

    /* walk all the recipient's certs */
    for (rcount = 0; rcerts[rcount] != NULL; rcount++) {
	SECItem *profile;
	NSSSMIMECapability **caps;
	int pref;

	/* the first cipher that matches in the user's SMIME profile gets
	 * "smime_cipher_map_count" votes; the next one gets "smime_cipher_map_count" - 1
	 * and so on. If every cipher matches, the last one gets 1 (one) vote */
	pref = smime_cipher_map_count;

	/* find recipient's SMIME profile */
	profile = CERT_FindSMimeProfile(rcerts[rcount]);

	if (profile != NULL && profile->data != NULL && profile->len > 0) {
	    /* we have a profile (still DER-encoded) */
	    caps = NULL;
	    /* decode it */
	    if (SEC_QuickDERDecodeItem(poolp, &caps,
                    NSSSMIMECapabilitiesTemplate, profile) == SECSuccess &&
		    caps != NULL)
	    {
		/* walk the SMIME capabilities for this recipient */
		for (i = 0; caps[i] != NULL; i++) {
		    cipher = nss_SMIME_FindCipherForSMIMECap(caps[i]);
		    mapi = smime_mapi_by_cipher(cipher);
		    if (mapi >= 0) {
			/* found the cipher */
			cipher_abilities[mapi]++;
			cipher_votes[mapi] += pref;
			--pref;
		    }
		}
	    }
	} else {
	    /* no profile found - so we can only assume that the user can do
	     * the mandatory algorithms which are RC2-40 (weak crypto) and
	     * 3DES (strong crypto), unless the user has an elliptic curve
	     * key.  For elliptic curve keys, RFC 5753 mandates support
	     * for AES 128 CBC. */
	    SECKEYPublicKey *key;
	    unsigned int pklen_bits;
	    KeyType key_type;

	    /*
	     * if recipient's public key length is > 512, vote for a strong cipher
	     * please not that the side effect of this is that if only one recipient
	     * has an export-level public key, the strong cipher is disabled.
	     *
	     * XXX This is probably only good for RSA keys.  What I would
	     * really like is a function to just say;  Is the public key in
	     * this cert an export-length key?  Then I would not have to
	     * know things like the value 512, or the kind of key, or what
	     * a subjectPublicKeyInfo is, etc.
	     */
	    key = CERT_ExtractPublicKey(rcerts[rcount]);
	    pklen_bits = 0;
	    key_type = nullKey;
	    if (key != NULL) {
		pklen_bits = SECKEY_PublicKeyStrengthInBits (key);
		key_type = SECKEY_GetPublicKeyType(key);
		SECKEY_DestroyPublicKey (key);
		key = NULL;
	    }

	    if (key_type == ecKey) {
		/* While RFC 5753 mandates support for AES-128 CBC, should use
		 * AES 256 if user's key provides more than 128 bits of
		 * security strength so that symmetric key is not weak link. */

		/* RC2-40 is not compatible with elliptic curve keys. */
		chosen_cipher = SMIME_DES_EDE3_168;
		if (pklen_bits > 256) {
		    cipher_abilities[aes256_mapi]++;
		    cipher_votes[aes256_mapi] += pref;
		    pref--;
		}
		cipher_abilities[aes128_mapi]++;
		cipher_votes[aes128_mapi] += pref;
		pref--;
		cipher_abilities[strong_mapi]++;
		cipher_votes[strong_mapi] += pref;
		pref--;
	    } else {
		if (pklen_bits > 512) {
		    /* cast votes for the strong algorithm */
		    cipher_abilities[strong_mapi]++;
		    cipher_votes[strong_mapi] += pref;
		    pref--;
		}

		/* always cast (possibly less) votes for the weak algorithm */
		cipher_abilities[weak_mapi]++;
		cipher_votes[weak_mapi] += pref;
	    } 
	}
	if (profile != NULL)
	    SECITEM_FreeItem(profile, PR_TRUE);
    }

    /* find cipher that is agreeable by all recipients and that has the most votes */
    max = 0;
    for (mapi = 0; mapi < smime_cipher_map_count; mapi++) {
	/* if not all of the recipients can do this, forget it */
	if (cipher_abilities[mapi] != rcount)
	    continue;
	/* if cipher is not enabled or not allowed by policy, forget it */
	if (!smime_cipher_map[mapi].enabled || !smime_cipher_map[mapi].allowed)
	    continue;
	/* now see if this one has more votes than the last best one */
	if (cipher_votes[mapi] >= max) {
	    /* if equal number of votes, prefer the ones further down in the list */
	    /* with the expectation that these are higher rated ciphers */
	    chosen_cipher = smime_cipher_map[mapi].cipher;
	    max = cipher_votes[mapi];
	}
    }
    /* if no common cipher was found, chosen_cipher stays at the default */

done:
    if (poolp != NULL)
	PORT_FreeArena (poolp, PR_FALSE);

    return chosen_cipher;
}
Beispiel #23
0
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);
}
Beispiel #24
0
/* MUST BE THREAD-SAFE */
static PK11SymKey *calc_dh_shared(const chunk_t g,	/* converted to SECItem */
				  /*const*/ SECKEYPrivateKey *privk,	/* NSS doesn't do const */
				  const struct oakley_group_desc *group,
				  const SECKEYPublicKey *local_pubk)
{
	struct timeval tv0;
	SECKEYPublicKey *remote_pubk;
	SECItem nss_g;
	PK11SymKey *dhshared;
	PRArenaPool *arena;
	SECStatus status;
	unsigned int dhshared_len;

	DBG(DBG_CRYPT,
		DBG_log("Started DH shared-secret computation in NSS:"));

	gettimeofday(&tv0, NULL);

	arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
	passert(arena != NULL);

	remote_pubk = (SECKEYPublicKey *)
		PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));

	remote_pubk->arena = arena;
	remote_pubk->keyType = dhKey;
	remote_pubk->pkcs11Slot = NULL;
	remote_pubk->pkcs11ID = CK_INVALID_HANDLE;

	nss_g.data = g.ptr;
	nss_g.len = (unsigned int)g.len;
	nss_g.type = siBuffer;

	status = SECITEM_CopyItem(remote_pubk->arena, &remote_pubk->u.dh.prime,
				  &local_pubk->u.dh.prime);
	passert(status == SECSuccess);

	status = SECITEM_CopyItem(remote_pubk->arena, &remote_pubk->u.dh.base,
				  &local_pubk->u.dh.base);
	passert(status == SECSuccess);

	status = SECITEM_CopyItem(remote_pubk->arena,
				  &remote_pubk->u.dh.publicValue, &nss_g);
	passert(status == SECSuccess);

	dhshared = PK11_PubDerive(privk, remote_pubk, PR_FALSE, NULL, NULL,
				  CKM_DH_PKCS_DERIVE,
				  CKM_CONCATENATE_DATA_AND_BASE,
				  CKA_DERIVE, group->bytes,
				  lsw_return_nss_password_file_info());
	passert(dhshared != NULL);

	dhshared_len = PK11_GetKeyLength(dhshared);
	if (group->bytes > dhshared_len) {
		DBG(DBG_CRYPT,
		    DBG_log("Dropped %lu leading zeros",
			    group->bytes - dhshared_len));
		chunk_t zeros;
		PK11SymKey *newdhshared;
		CK_KEY_DERIVATION_STRING_DATA string_params;
		SECItem params;

		zeros = hmac_pads(0x00, group->bytes - dhshared_len);
		params.data = (unsigned char *)&string_params;
		params.len = sizeof(string_params);
		string_params.pData = zeros.ptr;
		string_params.ulLen = zeros.len;

		newdhshared = PK11_Derive(dhshared,
					  CKM_CONCATENATE_DATA_AND_BASE,
					  &params,
					  CKM_CONCATENATE_DATA_AND_BASE,
					  CKA_DERIVE, 0);
		passert(newdhshared != NULL);
		PK11_FreeSymKey(dhshared);
		dhshared = newdhshared;
		freeanychunk(zeros);
	} else {
		DBG(DBG_CRYPT,
		    DBG_log("Dropped no leading zeros %d", dhshared_len));
	}

	/* nss_symkey_log(dhshared, "dhshared"); */

	DBG(DBG_CRYPT, {
		struct timeval tv1;
		unsigned long tv_diff;

		gettimeofday(&tv1, NULL);
		tv_diff = (tv1.tv_sec  - tv0.tv_sec) * 1000000 +
			  (tv1.tv_usec - tv0.tv_usec);
		DBG_log("calc_dh_shared(): time elapsed (%s): %ld usec",
			       enum_show(&oakley_group_names, group->group),
			       tv_diff);
	});
Beispiel #25
0
SECItemArray *
SECITEM_AllocArray(PLArenaPool *arena, SECItemArray *array, unsigned int len)
{
    SECItemArray *result = NULL;
    void *mark = NULL;

    if (array != NULL && array->items != NULL) {
        PORT_Assert(0);
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return NULL;
    }

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

    if (array == NULL) {
        if (arena != NULL) {
            result = PORT_ArenaZAlloc(arena, sizeof(SECItemArray));
        } else {
            result = PORT_ZAlloc(sizeof(SECItemArray));
        }
        if (result == NULL) {
            goto loser;
        }
    } else {
        result = array;
    }

    result->len = len;
    if (len) {
        if (arena != NULL) {
            result->items = PORT_ArenaZNewArray(arena, SECItem, len);
        } else {
            result->items = PORT_ZNewArray(SECItem, len);
        }
        if (result->items == NULL) {
            goto loser;
        }
    } else {
        result->items = NULL;
    }

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

loser:
    if ( arena != NULL ) {
        if (mark) {
            PORT_ArenaRelease(arena, mark);
        }
    } else {
        if (result != NULL && array == NULL) {
            PORT_Free(result);
        }
    }
    if (array != NULL) {
        array->items = NULL;
        array->len = 0;
    }
    return NULL;
}
Beispiel #26
0
SGNDigestInfo *
SGN_CreateDigestInfo(SECOidTag algorithm, const unsigned char *sig,
                     unsigned len)
{
    SGNDigestInfo *di;
    SECStatus rv;
    PLArenaPool *arena;
    SECItem *null_param;
    SECItem dummy_value;

    switch (algorithm) {
    case SEC_OID_MD2:
    case SEC_OID_MD5:
    case SEC_OID_SHA1:
    case SEC_OID_SHA224:
    case SEC_OID_SHA256:
    case SEC_OID_SHA384:
    case SEC_OID_SHA512:
        break;
    default:
        PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
        return NULL;
    }

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (arena == NULL) {
        return NULL;
    }

    di = (SGNDigestInfo *) PORT_ArenaZAlloc(arena, sizeof(SGNDigestInfo));
    if (di == NULL) {
        PORT_FreeArena(arena, PR_FALSE);
        return NULL;
    }

    di->arena = arena;

    /*
     * PKCS #1 specifies that the AlgorithmID must have a NULL parameter
     * (as opposed to no parameter at all).
     */
    dummy_value.data = NULL;
    dummy_value.len = 0;
    null_param = SEC_ASN1EncodeItem(NULL, NULL, &dummy_value, SEC_NullTemplate);
    if (null_param == NULL) {
        goto loser;
    }

    rv = SECOID_SetAlgorithmID(arena, &di->digestAlgorithm, algorithm,
                               null_param);

    SECITEM_FreeItem(null_param, PR_TRUE);

    if (rv != SECSuccess) {
        goto loser;
    }

    di->digest.data = (unsigned char *) PORT_ArenaAlloc(arena, len);
    if (di->digest.data == NULL) {
        goto loser;
    }

    di->digest.len = len;
    PORT_Memcpy(di->digest.data, sig, len);
    return di;

loser:
    SGN_DestroyDigestInfo(di);
    return NULL;
}
Beispiel #27
0
NSSLOWKEYPrivateKey *
nsslowkey_CopyPrivateKey(NSSLOWKEYPrivateKey *privKey)
{
    NSSLOWKEYPrivateKey *returnKey = NULL;
    SECStatus rv = SECFailure;
    PLArenaPool *poolp;

    if(!privKey) {
	return NULL;
    }

    poolp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if(!poolp) {
	return NULL;
    }

    returnKey = (NSSLOWKEYPrivateKey*)PORT_ArenaZAlloc(poolp, sizeof(NSSLOWKEYPrivateKey));
    if(!returnKey) {
	rv = SECFailure;
	goto loser;
    }

    returnKey->keyType = privKey->keyType;
    returnKey->arena = poolp;

    switch(privKey->keyType) {
	case NSSLOWKEYRSAKey:
	    rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.modulus), 
	    				&(privKey->u.rsa.modulus));
	    if(rv != SECSuccess) break;
	    rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.version), 
	    				&(privKey->u.rsa.version));
	    if(rv != SECSuccess) break;
	    rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.publicExponent), 
	    				&(privKey->u.rsa.publicExponent));
	    if(rv != SECSuccess) break;
	    rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.privateExponent), 
	    				&(privKey->u.rsa.privateExponent));
	    if(rv != SECSuccess) break;
	    rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.prime1), 
	    				&(privKey->u.rsa.prime1));
	    if(rv != SECSuccess) break;
	    rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.prime2), 
	    				&(privKey->u.rsa.prime2));
	    if(rv != SECSuccess) break;
	    rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.exponent1), 
	    				&(privKey->u.rsa.exponent1));
	    if(rv != SECSuccess) break;
	    rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.exponent2), 
	    				&(privKey->u.rsa.exponent2));
	    if(rv != SECSuccess) break;
	    rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.coefficient), 
	    				&(privKey->u.rsa.coefficient));
	    if(rv != SECSuccess) break;
	    break;
	case NSSLOWKEYDSAKey:
	    rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.publicValue),
	    				&(privKey->u.dsa.publicValue));
	    if(rv != SECSuccess) break;
	    rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.privateValue),
	    				&(privKey->u.dsa.privateValue));
	    if(rv != SECSuccess) break;
	    returnKey->u.dsa.params.arena = poolp;
	    rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.params.prime),
					&(privKey->u.dsa.params.prime));
	    if(rv != SECSuccess) break;
	    rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.params.subPrime),
					&(privKey->u.dsa.params.subPrime));
	    if(rv != SECSuccess) break;
	    rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.params.base),
					&(privKey->u.dsa.params.base));
	    if(rv != SECSuccess) break;
	    break;
	case NSSLOWKEYDHKey:
	    rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.publicValue),
	    				&(privKey->u.dh.publicValue));
	    if(rv != SECSuccess) break;
	    rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.privateValue),
	    				&(privKey->u.dh.privateValue));
	    if(rv != SECSuccess) break;
	    returnKey->u.dsa.params.arena = poolp;
	    rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.prime),
					&(privKey->u.dh.prime));
	    if(rv != SECSuccess) break;
	    rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.base),
					&(privKey->u.dh.base));
	    if(rv != SECSuccess) break;
	    break;
#ifndef NSS_DISABLE_ECC
	case NSSLOWKEYECKey:
	    rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.version),
	    				&(privKey->u.ec.version));
	    if(rv != SECSuccess) break;
	    rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.publicValue),
	    				&(privKey->u.ec.publicValue));
	    if(rv != SECSuccess) break;
	    rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.privateValue),
	    				&(privKey->u.ec.privateValue));
	    if(rv != SECSuccess) break;
	    returnKey->u.ec.ecParams.arena = poolp;
	    /* Copy the rest of the params */
	    rv = EC_CopyParams(poolp, &(returnKey->u.ec.ecParams),
			       &(privKey->u.ec.ecParams));
	    if (rv != SECSuccess) break;
	    break;
#endif /* NSS_DISABLE_ECC */
	default:
	    rv = SECFailure;
    }

loser:

    if(rv != SECSuccess) {
	PORT_FreeArena(poolp, PR_TRUE);
	returnKey = NULL;
    }

    return returnKey;
}
static SECStatus 
dsa_NewKeyExtended(const PQGParams *params, const SECItem * seed,
                   DSAPrivateKey **privKey)
{
    mp_int p, g;
    mp_int x, y;
    mp_err err;
    PRArenaPool *arena;
    DSAPrivateKey *key;
    /* Check args. */
    if (!params || !privKey || !seed || !seed->data) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    }
    /* Initialize an arena for the DSA key. */
    arena = PORT_NewArena(NSS_FREEBL_DSA_DEFAULT_CHUNKSIZE);
    if (!arena) {
	PORT_SetError(SEC_ERROR_NO_MEMORY);
	return SECFailure;
    }
    key = (DSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DSAPrivateKey));
    if (!key) {
	PORT_SetError(SEC_ERROR_NO_MEMORY);
	PORT_FreeArena(arena, PR_TRUE);
	return SECFailure;
    }
    key->params.arena = arena;
    /* Initialize MPI integers. */
    MP_DIGITS(&p) = 0;
    MP_DIGITS(&g) = 0;
    MP_DIGITS(&x) = 0;
    MP_DIGITS(&y) = 0;
    CHECK_MPI_OK( mp_init(&p) );
    CHECK_MPI_OK( mp_init(&g) );
    CHECK_MPI_OK( mp_init(&x) );
    CHECK_MPI_OK( mp_init(&y) );
    /* Copy over the PQG params */
    CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.prime,
                                          &params->prime) );
    CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.subPrime,
                                          &params->subPrime) );
    CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.base, &params->base) );
    /* Convert stored p, g, and received x into MPI integers. */
    SECITEM_TO_MPINT(params->prime, &p);
    SECITEM_TO_MPINT(params->base,  &g);
    OCTETS_TO_MPINT(seed->data, &x, seed->len);
    /* Store x in private key */
    SECITEM_AllocItem(arena, &key->privateValue, seed->len);
    PORT_Memcpy(key->privateValue.data, seed->data, seed->len);
    /* Compute public key y = g**x mod p */
    CHECK_MPI_OK( mp_exptmod(&g, &x, &p, &y) );
    /* Store y in public key */
    MPINT_TO_SECITEM(&y, &key->publicValue, arena);
    *privKey = key;
    key = NULL;
cleanup:
    mp_clear(&p);
    mp_clear(&g);
    mp_clear(&x);
    mp_clear(&y);
    if (key)
	PORT_FreeArena(key->params.arena, PR_TRUE);
    if (err) {
	translate_mpi_error(err);
	return SECFailure;
    }
    return SECSuccess;
}
Beispiel #29
0
/* Generates a new EC key pair. The private key is a supplied
 * value and the public key is the result of performing a scalar 
 * point multiplication of that value with the curve's base point.
 */
SECStatus 
ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey, 
    const unsigned char *privKeyBytes, int privKeyLen)
{
    SECStatus rv = SECFailure;
#ifndef NSS_DISABLE_ECC
    PLArenaPool *arena;
    ECPrivateKey *key;
    mp_int k;
    mp_err err = MP_OKAY;
    int len;

#if EC_DEBUG
    printf("ec_NewKey called\n");
#endif
    MP_DIGITS(&k) = 0;

    if (!ecParams || !privKey || !privKeyBytes || (privKeyLen < 0)) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    }

    /* Initialize an arena for the EC key. */
    if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE)))
	return SECFailure;

    key = (ECPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(ECPrivateKey));
    if (!key) {
	PORT_FreeArena(arena, PR_TRUE);
	return SECFailure;
    }

    /* Set the version number (SEC 1 section C.4 says it should be 1) */
    SECITEM_AllocItem(arena, &key->version, 1);
    key->version.data[0] = 1;

    /* Copy all of the fields from the ECParams argument to the
     * ECParams structure within the private key.
     */
    key->ecParams.arena = arena;
    key->ecParams.type = ecParams->type;
    key->ecParams.fieldID.size = ecParams->fieldID.size;
    key->ecParams.fieldID.type = ecParams->fieldID.type;
    if (ecParams->fieldID.type == ec_field_GFp) {
	CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.prime,
	    &ecParams->fieldID.u.prime));
    } else {
	CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.poly,
	    &ecParams->fieldID.u.poly));
    }
    key->ecParams.fieldID.k1 = ecParams->fieldID.k1;
    key->ecParams.fieldID.k2 = ecParams->fieldID.k2;
    key->ecParams.fieldID.k3 = ecParams->fieldID.k3;
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.a,
	&ecParams->curve.a));
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.b,
	&ecParams->curve.b));
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.seed,
	&ecParams->curve.seed));
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.base,
	&ecParams->base));
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.order,
	&ecParams->order));
    key->ecParams.cofactor = ecParams->cofactor;
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.DEREncoding,
	&ecParams->DEREncoding));
    key->ecParams.name = ecParams->name;
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curveOID,
	&ecParams->curveOID));

    len = (ecParams->fieldID.size + 7) >> 3;
    SECITEM_AllocItem(arena, &key->publicValue, 2*len + 1);
    len = ecParams->order.len;
    SECITEM_AllocItem(arena, &key->privateValue, len);

    /* Copy private key */
    if (privKeyLen >= len) {
	memcpy(key->privateValue.data, privKeyBytes, len);
    } else {
	memset(key->privateValue.data, 0, (len - privKeyLen));
	memcpy(key->privateValue.data + (len - privKeyLen), privKeyBytes, privKeyLen);
    }

    /* Compute corresponding public key */
    CHECK_MPI_OK( mp_init(&k) );
    CHECK_MPI_OK( mp_read_unsigned_octets(&k, key->privateValue.data, 
	(mp_size) len) );

    rv = ec_points_mul(ecParams, &k, NULL, NULL, &(key->publicValue));
    if (rv != SECSuccess) goto cleanup;
    *privKey = key;

cleanup:
    mp_clear(&k);
    if (rv)
	PORT_FreeArena(arena, PR_TRUE);

#if EC_DEBUG
    printf("ec_NewKey returning %s\n", 
	(rv == SECSuccess) ? "success" : "failure");
#endif
#else
    PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
#endif /* NSS_DISABLE_ECC */

    return rv;

}
Beispiel #30
0
SECStatus 
DH_NewKey(DHParams *params, DHPrivateKey **privKey)
{
    PLArenaPool *arena;
    DHPrivateKey *key;
    mp_int g, xa, p, Ya;
    mp_err   err = MP_OKAY;
    SECStatus rv = SECSuccess;
    if (!params || !privKey) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    }
    arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
    if (!arena) {
	PORT_SetError(SEC_ERROR_NO_MEMORY);
	return SECFailure;
    }
    key = (DHPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DHPrivateKey));
    if (!key) {
	PORT_SetError(SEC_ERROR_NO_MEMORY);
	PORT_FreeArena(arena, PR_TRUE);
	return SECFailure;
    }
    key->arena = arena;
    MP_DIGITS(&g)  = 0;
    MP_DIGITS(&xa) = 0;
    MP_DIGITS(&p)  = 0;
    MP_DIGITS(&Ya) = 0;
    CHECK_MPI_OK( mp_init(&g)  );
    CHECK_MPI_OK( mp_init(&xa) );
    CHECK_MPI_OK( mp_init(&p)  );
    CHECK_MPI_OK( mp_init(&Ya) );
    /* Set private key's p */
    CHECK_SEC_OK( SECITEM_CopyItem(arena, &key->prime, &params->prime) );
    SECITEM_TO_MPINT(key->prime, &p);
    /* Set private key's g */
    CHECK_SEC_OK( SECITEM_CopyItem(arena, &key->base, &params->base) );
    SECITEM_TO_MPINT(key->base, &g);
    /* Generate private key xa */
    SECITEM_AllocItem(arena, &key->privateValue,
                      dh_GetSecretKeyLen(params->prime.len));
    CHECK_SEC_OK(RNG_GenerateGlobalRandomBytes(key->privateValue.data, 
                                  key->privateValue.len));
    SECITEM_TO_MPINT( key->privateValue, &xa );
    /* xa < p */
    CHECK_MPI_OK( mp_mod(&xa, &p, &xa) );
    /* Compute public key Ya = g ** xa mod p */
    CHECK_MPI_OK( mp_exptmod(&g, &xa, &p, &Ya) );
    MPINT_TO_SECITEM(&Ya, &key->publicValue, key->arena);
    *privKey = key;
cleanup:
    mp_clear(&g);
    mp_clear(&xa);
    mp_clear(&p);
    mp_clear(&Ya);
    if (err) {
	MP_TO_SEC_ERROR(err);
	rv = SECFailure;
    }
    if (rv) {
	*privKey = NULL;
	PORT_FreeArena(arena, PR_TRUE);
    }
    return rv;
}