summaryrefslogtreecommitdiff
path: root/security/nss/lib/util/secdig.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/util/secdig.c')
-rw-r--r--security/nss/lib/util/secdig.c232
1 files changed, 232 insertions, 0 deletions
diff --git a/security/nss/lib/util/secdig.c b/security/nss/lib/util/secdig.c
new file mode 100644
index 000000000..056068222
--- /dev/null
+++ b/security/nss/lib/util/secdig.c
@@ -0,0 +1,232 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ *
+ * $Id$
+ */
+#include "secdig.h"
+
+#include "secoid.h"
+#include "secasn1.h"
+#include "secerr.h"
+
+/*
+ * XXX OLD Template. Once all uses have been switched over to new one,
+ * remove this.
+ */
+DERTemplate SGNDigestInfoTemplate[] = {
+ { DER_SEQUENCE,
+ 0, NULL, sizeof(SGNDigestInfo) },
+ { DER_INLINE,
+ offsetof(SGNDigestInfo,digestAlgorithm),
+ SECAlgorithmIDTemplate, },
+ { DER_OCTET_STRING,
+ offsetof(SGNDigestInfo,digest), },
+ { 0, }
+};
+
+/* XXX See comment below about SGN_DecodeDigestInfo -- keep this static! */
+/* XXX Changed from static -- need to change name? */
+const SEC_ASN1Template sgn_DigestInfoTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(SGNDigestInfo) },
+ { SEC_ASN1_INLINE,
+ offsetof(SGNDigestInfo,digestAlgorithm),
+ SECOID_AlgorithmIDTemplate },
+ { SEC_ASN1_OCTET_STRING,
+ offsetof(SGNDigestInfo,digest) },
+ { 0 }
+};
+
+SEC_ASN1_CHOOSER_IMPLEMENT(sgn_DigestInfoTemplate)
+
+/*
+ * XXX Want to have a SGN_DecodeDigestInfo, like:
+ * SGNDigestInfo *SGN_DecodeDigestInfo(SECItem *didata);
+ * that creates a pool and allocates from it and decodes didata into
+ * the newly allocated DigestInfo structure. Then fix secvfy.c (it
+ * will no longer need an arena itself) to call this and then call
+ * DestroyDigestInfo when it is done, then can remove the old template
+ * above and keep our new template static and "hidden".
+ */
+
+/*
+ * XXX It might be nice to combine the following two functions (create
+ * and encode). I think that is all anybody ever wants to do anyway.
+ */
+
+SECItem *
+SGN_EncodeDigestInfo(PRArenaPool *poolp, SECItem *dest, SGNDigestInfo *diginfo)
+{
+ return SEC_ASN1EncodeItem (poolp, dest, diginfo, sgn_DigestInfoTemplate);
+}
+
+SGNDigestInfo *
+SGN_CreateDigestInfo(SECOidTag algorithm, unsigned char *sig, unsigned len)
+{
+ SGNDigestInfo *di;
+ SECStatus rv;
+ PRArenaPool *arena;
+ SECItem *null_param;
+ SECItem dummy_value;
+
+ switch (algorithm) {
+ case SEC_OID_MD2:
+ case SEC_OID_MD5:
+ case SEC_OID_SHA1:
+ 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;
+}
+
+SGNDigestInfo *
+SGN_DecodeDigestInfo(SECItem *didata)
+{
+ PRArenaPool *arena;
+ SGNDigestInfo *di;
+ SECStatus rv = SECFailure;
+
+ arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
+ if(arena == NULL)
+ return NULL;
+
+ di = (SGNDigestInfo *)PORT_ArenaZAlloc(arena, sizeof(SGNDigestInfo));
+ if(di != NULL)
+ {
+ di->arena = arena;
+ rv = SEC_ASN1DecodeItem(arena, di, sgn_DigestInfoTemplate, didata);
+ }
+
+ if((di == NULL) || (rv != SECSuccess))
+ {
+ PORT_FreeArena(arena, PR_TRUE);
+ di = NULL;
+ }
+
+ return di;
+}
+
+void
+SGN_DestroyDigestInfo(SGNDigestInfo *di)
+{
+ if (di && di->arena) {
+ PORT_FreeArena(di->arena, PR_FALSE);
+ }
+
+ return;
+}
+
+SECStatus
+SGN_CopyDigestInfo(PRArenaPool *poolp, SGNDigestInfo *a, SGNDigestInfo *b)
+{
+ SECStatus rv;
+ void *mark;
+
+ if((poolp == NULL) || (a == NULL) || (b == NULL))
+ return SECFailure;
+
+ mark = PORT_ArenaMark(poolp);
+ a->arena = poolp;
+ rv = SECOID_CopyAlgorithmID(poolp, &a->digestAlgorithm,
+ &b->digestAlgorithm);
+ if (rv == SECSuccess)
+ rv = SECITEM_CopyItem(poolp, &a->digest, &b->digest);
+
+ if (rv != SECSuccess) {
+ PORT_ArenaRelease(poolp, mark);
+ } else {
+ PORT_ArenaUnmark(poolp, mark);
+ }
+
+ return rv;
+}
+
+SECComparison
+SGN_CompareDigestInfo(SGNDigestInfo *a, SGNDigestInfo *b)
+{
+ SECComparison rv;
+
+ /* Check signature algorithm's */
+ rv = SECOID_CompareAlgorithmID(&a->digestAlgorithm, &b->digestAlgorithm);
+ if (rv) return rv;
+
+ /* Compare signature block length's */
+ rv = SECITEM_CompareItem(&a->digest, &b->digest);
+ return rv;
+}