From c84f3896efeefeff3d0a74e45eba8e3bff472715 Mon Sep 17 00:00:00 2001 From: deuce <> Date: Thu, 22 Feb 2018 10:44:10 +0000 Subject: [PATCH] Add new create_signature() method. Don't force set the label, require the caller to set it. Fix up ASN.1 parsing of RSA certificates. --- src/sbbs3/js_cryptcon.c | 90 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 83 insertions(+), 7 deletions(-) diff --git a/src/sbbs3/js_cryptcon.c b/src/sbbs3/js_cryptcon.c index 674b4e7403..c2080335c7 100644 --- a/src/sbbs3/js_cryptcon.c +++ b/src/sbbs3/js_cryptcon.c @@ -12,6 +12,7 @@ struct private_data { CRYPT_CONTEXT ctx; }; +static JSClass js_cryptcon_class; static const char* getprivate_failure = "line %d %s %s JS_GetPrivate failed"; // Helpers @@ -91,6 +92,7 @@ static void js_simple_asn1(unsigned char *data, size_t len, JSContext *cx, JSObj { unsigned char t; size_t off=0; + size_t off2; size_t sz; char *e; char *n; @@ -116,7 +118,20 @@ static void js_simple_asn1(unsigned char *data, size_t len, JSContext *cx, JSObj if (strncmp((char *)data+off, "\x2a\x86\x48\x86\xF7\x0D\x01\x01\x01", 9)==0) { // YEP! off += sz; - off += 9; + for (; off < len;) { + off2 = off; + t = js_asn1_type(data, len, &off2); + if (t == 2) + break; + off = off2; + sz = js_asn1_len(data,len,&off); + if (t != 48 && t != 3) + off += sz; + if (t == 3) + off++; + } + if (off >= len) + return; if (js_asn1_type(data, len, &off) == 2) { sz = js_asn1_len(data,len,&off); n = malloc(sz); @@ -285,7 +300,6 @@ js_generate_key(JSContext *cx, uintN argc, jsval *arglist) JSObject *obj=JS_THIS_OBJECT(cx, arglist); jsrefcount rc; int status; - char kname[32]; if ((p=(struct private_data *)JS_GetPrivate(cx,obj))==NULL) { JS_ReportError(cx, getprivate_failure, WHERE); @@ -293,10 +307,7 @@ js_generate_key(JSContext *cx, uintN argc, jsval *arglist) } rc = JS_SUSPENDREQUEST(cx); - sprintf(kname, "Key-%d", p->ctx); - status = cryptSetAttributeString(p->ctx, CRYPT_CTXINFO_LABEL, kname, strlen(kname)); - if (status == CRYPT_OK) - status = cryptGenerateKey(p->ctx); + status = cryptGenerateKey(p->ctx); JS_RESUMEREQUEST(cx, rc); if (status == CRYPT_OK) js_create_key_object(cx, obj); @@ -458,6 +469,67 @@ js_decrypt(JSContext *cx, uintN argc, jsval *arglist) return js_do_encrption(cx, argc, arglist, FALSE); } +static JSBool +js_create_signature(JSContext *cx, uintN argc, jsval *arglist) +{ + struct private_data* p; + struct private_data* scp; + JSObject *sigCtx; + JSObject *obj; + jsval *argv; + int len; + char *signature = NULL; + int status; + jsrefcount rc; + JSString* str; + + if (!js_argc(cx, argc, 1)) + return JS_FALSE; + + argv = JS_ARGV(cx, arglist); + + obj = JS_THIS_OBJECT(cx, arglist); + if ((p=(struct private_data *)JS_GetPrivate(cx,obj))==NULL) { + JS_ReportError(cx, getprivate_failure, WHERE); + return JS_FALSE; + } + sigCtx = JSVAL_TO_OBJECT(argv[0]); + if (!JS_InstanceOf(cx, sigCtx, &js_cryptcon_class, NULL)) + return JS_FALSE; + HANDLE_PENDING(cx, sigCtx); + if ((scp=(struct private_data *)JS_GetPrivate(cx,sigCtx))==NULL) { + JS_ReportError(cx, getprivate_failure, WHERE); + return JS_FALSE; + } + + rc = JS_SUSPENDREQUEST(cx); + status = cryptCreateSignature(NULL, 0, &len, scp->ctx, p->ctx); + if (cryptStatusError(status)) { + JS_RESUMEREQUEST(cx, rc); + js_cryptcon_error(cx, p->ctx, status); + return JS_FALSE; + } + signature = malloc(len); + if (signature == NULL) { + lprintf(LOG_ERR, "Unable to allocate %lu bytes\n", len); + JS_RESUMEREQUEST(cx, rc); + return JS_FALSE; + } + status = cryptCreateSignature(signature, len, &len, scp->ctx, p->ctx); + JS_RESUMEREQUEST(cx, rc); + if (cryptStatusError(status)) { + free(signature); + js_cryptcon_error(cx, p->ctx, status); + return JS_FALSE; + } + str = JS_NewStringCopyN(cx, signature, len); + free(signature); + if(str==NULL) + return(JS_FALSE); + JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(str)); + return JS_TRUE; +} + // Properties enum { @@ -632,7 +704,6 @@ js_cryptcon_attrstr_get(JSContext *cx, jsval *vp, CRYPT_CONTEXT ctx, CRYPT_ATTRI status = cryptGetAttributeString(ctx, type, NULL, &len); if (cryptStatusError(status)) { *vp = JSVAL_VOID; - return JS_TRUE; js_cryptcon_error(cx, ctx, status); return JS_FALSE; } @@ -687,6 +758,7 @@ js_cryptcon_get(JSContext *cx, JSObject *obj, jsid id, jsval *vp) case CRYPTCON_PROP_MODE: return js_cryptcon_attr_get(cx, vp, p->ctx, CRYPT_CTXINFO_MODE); case CRYPTCON_PROP_HASHVALUE: + cryptEncrypt(p->ctx, p, 0); return js_cryptcon_attrstr_get(cx, vp, p->ctx, CRYPT_CTXINFO_HASHVALUE); case CRYPTCON_PROP_IV: return js_cryptcon_attrstr_get(cx, vp, p->ctx, CRYPT_CTXINFO_IV); @@ -741,6 +813,10 @@ static jsSyncMethodSpec js_cryptcon_functions[] = { ,JSDOCSTR("Decrypt the string and return as a new string.") ,316 }, + {"create_signature",js_create_signature,0, JSTYPE_STRING, "sigContext" + ,JSDOCSTR("Create a signature signed with the sigContext CryptContext object.") + ,316 + }, {0} }; -- GitLab