예제 #1
0
SECStatus
NSS_CMSSignedData_Decode_BeforeData(NSSCMSSignedData *sigd)
{
    if (!sigd) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }
    /* set up the digests */
    if (sigd->digestAlgorithms != NULL && sigd->digests == NULL) {
        /* if digests are already there, do nothing */
        sigd->contentInfo.digcx = NSS_CMSDigestContext_StartMultiple(sigd->digestAlgorithms);
        if (sigd->contentInfo.digcx == NULL)
            return SECFailure;
    }
    return SECSuccess;
}
예제 #2
0
SECStatus
NSS_CMSSignedData_Encode_BeforeData(NSSCMSSignedData *sigd)
{
    if (!sigd) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }
    /* set up the digests */
    if (sigd->digests && sigd->digests[0]) {
        sigd->contentInfo.digcx = NULL; /* don't attempt to make new ones. */
    } else if (sigd->digestAlgorithms != NULL) {
        sigd->contentInfo.digcx =
            NSS_CMSDigestContext_StartMultiple(sigd->digestAlgorithms);
        if (sigd->contentInfo.digcx == NULL)
            return SECFailure;
    }
    return SECSuccess;
}
예제 #3
0
SECStatus
NSS_CMSSignedData_Decode_BeforeData(NSSCMSSignedData *sigd)
{
    SECStatus rv;
    if (!sigd) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }
    rv = NSS_CMSContentInfo_Private_Init(&sigd->contentInfo);
    if (rv != SECSuccess) {
	return SECFailure;
    }
    /* handle issue with Windows 2003 servers and kerberos */
    if (sigd->digestAlgorithms != NULL) {
	int i;
	for (i=0; sigd->digestAlgorithms[i] != NULL; i++) {
	    SECAlgorithmID *algid = sigd->digestAlgorithms[i];
	    SECOidTag senttag= SECOID_FindOIDTag(&algid->algorithm);
	    SECOidTag maptag = NSS_CMSUtil_MapSignAlgs(senttag);

	    if (maptag != senttag) {
		SECOidData *hashoid = SECOID_FindOIDByTag(maptag);
		rv = SECITEM_CopyItem(sigd->cmsg->poolp, &algid->algorithm 
							,&hashoid->oid);
		if (rv != SECSuccess) {
		    return rv;
		}
	    }
	}
    }

    /* set up the digests */
    if (sigd->digestAlgorithms != NULL && sigd->digests == NULL) {
	/* if digests are already there, do nothing */
	sigd->contentInfo.privateInfo->digcx = NSS_CMSDigestContext_StartMultiple(sigd->digestAlgorithms);
	if (sigd->contentInfo.privateInfo->digcx == NULL)
	    return SECFailure;
    }
    return SECSuccess;
}
예제 #4
0
파일: nss.c 프로젝트: Babar/check_multi
static enum okay
getdig(struct message *m, int n, SECItem ***digests,
		PLArenaPool **poolp, SECAlgorithmID **algids)
{
	char	*ct, *pt, *boundary;
	char	*buf = NULL;
	size_t	bufsize = 0, buflen, count, boundlen;
	int	part;
	int	nl;
	FILE	*fp;
	NSSCMSDigestContext	*digctx;

	*poolp = PORT_NewArena(1024);
	if ((ct = hfield("content-type", m)) == NULL ||
			strncmp(ct, "multipart/signed", 16) ||
			(pt = mime_getparam("protocol", ct)) == NULL ||
			strcmp(pt, "application/x-pkcs7-signature") &&
			 strcmp(pt, "application/pkcs7-signature") ||
			(boundary = mime_getboundary(ct)) == NULL) {
		fprintf(stderr,
			"Message %d is not an S/MIME signed message.\n", n);
		return STOP;
	}
	boundlen = strlen(boundary);
	if ((digctx = NSS_CMSDigestContext_StartMultiple(algids)) == NULL) {
		fprintf(stderr, "Cannot start digest computation.\n");
		return STOP;
	}
	if ((fp = setinput(&mb, m, NEED_BODY)) == NULL) {
		return STOP;
	}
	count = m->m_size;
	part = 0;
	nl = 0;
	while (fgetline(&buf, &bufsize, &count, &buflen, fp, 0) != NULL) {
		if (buflen >= boundlen + 1 &&
				strncmp(buf, boundary, boundlen) == 0) {
			if (buf[boundlen] == '\n') {
				if (++part >= 2)
					break;
				continue;
			}
			if (buf[boundlen] == '-' && buf[boundlen+1] == '-' &&
					buf[boundlen+2] == '\n')
				break;
		}
		if (part == 1) {
			if (nl) {
				NSS_CMSDigestContext_Update(digctx,
						(unsigned char *)"\r\n", 2);
				nl = 0;
			}
			if (buf[buflen-1] == '\n') {
				nl = 1;
				buflen--;
			}
			NSS_CMSDigestContext_Update(digctx,
					(unsigned char *)buf, buflen);
			continue;
		}
	}
	free(buf);
	if (NSS_CMSDigestContext_FinishMultiple(digctx,
				*poolp, digests) != SECSuccess) {
		fprintf(stderr, "Error creating digest for message %d\n", n);
		return STOP;
	}
	return OKAY;
}
예제 #5
0
static CamelCipherValidity *
sm_verify_cmsg(CamelCipherContext *context, NSSCMSMessage *cmsg, CamelStream *extstream, CamelException *ex)
{
	struct _CamelSMIMEContextPrivate *p = ((CamelSMIMEContext *)context)->priv;
	NSSCMSSignedData *sigd = NULL;
	NSSCMSEnvelopedData *envd;
	NSSCMSEncryptedData *encd;
	SECAlgorithmID **digestalgs;
	NSSCMSDigestContext *digcx;
	int count, i, nsigners, j;
	SECItem **digests;
	PLArenaPool *poolp = NULL;
	CamelStreamMem *mem;
	NSSCMSVerificationStatus status;
	CamelCipherValidity *valid;
	GString *description;

	description = g_string_new("");
	valid = camel_cipher_validity_new();
	camel_cipher_validity_set_valid(valid, TRUE);
	status = NSSCMSVS_Unverified;

	/* NB: this probably needs to go into a decoding routine that can be used for processing
	   enveloped data too */
	count = NSS_CMSMessage_ContentLevelCount(cmsg);
	for (i = 0; i < count; i++) {
		NSSCMSContentInfo *cinfo = NSS_CMSMessage_ContentLevel(cmsg, i);
		SECOidTag typetag = NSS_CMSContentInfo_GetContentTypeTag(cinfo);

		switch (typetag) {
		case SEC_OID_PKCS7_SIGNED_DATA:
			sigd = (NSSCMSSignedData *)NSS_CMSContentInfo_GetContent(cinfo);
			if (sigd == NULL) {
				camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("No signed data in signature"));
				goto fail;
			}

			/* need to build digests of the content */
			if (!NSS_CMSSignedData_HasDigests(sigd)) {
				if (extstream == NULL) {
					camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Digests missing from enveloped data"));
					goto fail;
				}

				if ((poolp = PORT_NewArena(1024)) == NULL) {
					camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, g_strerror (ENOMEM));
					goto fail;
				}

				digestalgs = NSS_CMSSignedData_GetDigestAlgs(sigd);

				digcx = NSS_CMSDigestContext_StartMultiple(digestalgs);
				if (digcx == NULL) {
					camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot calculate digests"));
					goto fail;
				}

				mem = (CamelStreamMem *)camel_stream_mem_new();
				camel_stream_write_to_stream(extstream, (CamelStream *)mem);
				NSS_CMSDigestContext_Update(digcx, mem->buffer->data, mem->buffer->len);
				camel_object_unref(mem);

				if (NSS_CMSDigestContext_FinishMultiple(digcx, poolp, &digests) != SECSuccess) {
					camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot calculate digests"));
					goto fail;
				}

				if (NSS_CMSSignedData_SetDigests(sigd, digestalgs, digests) != SECSuccess) {
					camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot set message digests"));
					goto fail;
				}

				PORT_FreeArena(poolp, PR_FALSE);
				poolp = NULL;
			}

			/* import all certificates present */
			if (NSS_CMSSignedData_ImportCerts(sigd, p->certdb, certUsageEmailSigner, PR_TRUE) != SECSuccess) {
				camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Certificate import failed"));
				goto fail;
			}

			if (NSS_CMSSignedData_ImportCerts(sigd, p->certdb, certUsageEmailRecipient, PR_TRUE) != SECSuccess) {
				camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Certificate import failed"));
				goto fail;
			}

			/* check for certs-only message */
			nsigners = NSS_CMSSignedData_SignerInfoCount(sigd);
			if (nsigners == 0) {

				/* already imported certs above, not sure what usage we should use here or if this isn't handled above */
				if (NSS_CMSSignedData_VerifyCertsOnly(sigd, p->certdb, certUsageEmailSigner) != SECSuccess) {
					g_string_printf(description, _("Certificate is the only message, cannot verify certificates"));
				} else {
					status = NSSCMSVS_GoodSignature;
					g_string_printf(description, _("Certificate is the only message, certificates imported and verified"));
				}
			} else {
				if (!NSS_CMSSignedData_HasDigests(sigd)) {
					camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot find signature digests"));
					goto fail;
				}

				for (j = 0; j < nsigners; j++) {
					NSSCMSSignerInfo *si;
					char *cn, *em;

					si = NSS_CMSSignedData_GetSignerInfo(sigd, j);
					NSS_CMSSignedData_VerifySignerInfo(sigd, j, p->certdb, certUsageEmailSigner);

					status = NSS_CMSSignerInfo_GetVerificationStatus(si);

					cn = NSS_CMSSignerInfo_GetSignerCommonName(si);
					em = NSS_CMSSignerInfo_GetSignerEmailAddress(si);

					g_string_append_printf(description, _("Signer: %s <%s>: %s\n"),
							       cn?cn:"<unknown>", em?em:"<unknown>",
							       sm_status_description(status));

					camel_cipher_validity_add_certinfo(valid, CAMEL_CIPHER_VALIDITY_SIGN, cn, em);

					if (cn)
						PORT_Free(cn);
					if (em)
						PORT_Free(em);

					if (status != NSSCMSVS_GoodSignature)
						camel_cipher_validity_set_valid(valid, FALSE);
				}
			}
			break;
		case SEC_OID_PKCS7_ENVELOPED_DATA:
			envd = (NSSCMSEnvelopedData *)NSS_CMSContentInfo_GetContent(cinfo);
			break;
		case SEC_OID_PKCS7_ENCRYPTED_DATA:
			encd = (NSSCMSEncryptedData *)NSS_CMSContentInfo_GetContent(cinfo);
			break;
		case SEC_OID_PKCS7_DATA:
			break;
		default:
			break;
		}
	}

	camel_cipher_validity_set_valid(valid, status == NSSCMSVS_GoodSignature);
	camel_cipher_validity_set_description(valid, description->str);
	g_string_free(description, TRUE);

	return valid;

fail:
	camel_cipher_validity_free(valid);
	g_string_free(description, TRUE);

	return NULL;
}