/* * Decode a string to a key. Return 0 on success. */ int kn_decode_key(struct keynote_deckey *dc, char *key, int keytype) { void *kk = NULL; X509 *px509Cert; EVP_PKEY *pPublicKey; unsigned char *ptr = NULL, *decoded = NULL; int encoding, internalencoding; long len = 0; keynote_errno = 0; if (keytype == KEYNOTE_PRIVATE_KEY) dc->dec_algorithm = keynote_get_private_key_algorithm(key, &encoding, &internalencoding); else dc->dec_algorithm = keynote_get_key_algorithm(key, &encoding, &internalencoding); if (dc->dec_algorithm == KEYNOTE_ALGORITHM_NONE) { if ((dc->dec_key = strdup(key)) == NULL) { keynote_errno = ERROR_MEMORY; return -1; } return 0; } key = strchr(key, ':'); /* Move forward, to the Encoding. We're guaranteed * to have a ':' character, since this is a key */ key++; /* Remove ASCII encoding */ switch (encoding) { case ENCODING_NONE: break; case ENCODING_HEX: len = strlen(key) / 2; if (kn_decode_hex(key, (char **) &decoded) != 0) return -1; ptr = decoded; break; case ENCODING_BASE64: len = strlen(key); if (len % 4) /* Base64 encoding must be a multiple of 4 */ { keynote_errno = ERROR_SYNTAX; return -1; } len = 3 * (len / 4); decoded = calloc(len, sizeof(unsigned char)); ptr = decoded; if (decoded == NULL) { keynote_errno = ERROR_MEMORY; return -1; } if ((len = kn_decode_base64(key, decoded, len)) == -1) return -1; break; case ENCODING_NATIVE: decoded = strdup(key); if (decoded == NULL) { keynote_errno = ERROR_MEMORY; return -1; } len = strlen(key); ptr = decoded; break; default: keynote_errno = ERROR_SYNTAX; return -1; } /* DSA-HEX */ if ((dc->dec_algorithm == KEYNOTE_ALGORITHM_DSA) && (internalencoding == INTERNAL_ENC_ASN1)) { dc->dec_key = DSA_new(); if (dc->dec_key == NULL) { keynote_errno = ERROR_MEMORY; return -1; } kk = dc->dec_key; if (keytype == KEYNOTE_PRIVATE_KEY) { if (d2i_DSAPrivateKey((DSA **) &kk,(const unsigned char **) &decoded, len) == NULL) { free(ptr); DSA_free(kk); keynote_errno = ERROR_SYNTAX; /* Could be a memory error */ return -1; } } else { if (d2i_DSAPublicKey((DSA **) &kk, (const unsigned char **) &decoded, len) == NULL) { free(ptr); DSA_free(kk); keynote_errno = ERROR_SYNTAX; /* Could be a memory error */ return -1; } } free(ptr); return 0; } /* RSA-PKCS1-HEX */ if ((dc->dec_algorithm == KEYNOTE_ALGORITHM_RSA) && (internalencoding == INTERNAL_ENC_PKCS1)) { dc->dec_key = RSA_new(); if (dc->dec_key == NULL) { keynote_errno = ERROR_MEMORY; return -1; } kk = dc->dec_key; if (keytype == KEYNOTE_PRIVATE_KEY) { if (d2i_RSAPrivateKey((RSA **) &kk, (const unsigned char **) &decoded, len) == NULL) { free(ptr); RSA_free(kk); keynote_errno = ERROR_SYNTAX; /* Could be a memory error */ return -1; } if (RSA_blinding_on((RSA *) kk, NULL) != 1) { free(ptr); RSA_free(kk); keynote_errno = ERROR_MEMORY; return -1; } } else { if (d2i_RSAPublicKey((RSA **) &kk, (const unsigned char **) &decoded, len) == NULL) { free(ptr); RSA_free(kk); keynote_errno = ERROR_SYNTAX; /* Could be a memory error */ return -1; } } free(ptr); return 0; } /* X509 Cert */ if ((dc->dec_algorithm == KEYNOTE_ALGORITHM_X509) && (internalencoding == INTERNAL_ENC_ASN1) && (keytype == KEYNOTE_PUBLIC_KEY)) { if ((px509Cert = X509_new()) == NULL) { free(ptr); keynote_errno = ERROR_MEMORY; return -1; } if(d2i_X509(&px509Cert, (const unsigned char **)&decoded, len) == NULL) { free(ptr); X509_free(px509Cert); keynote_errno = ERROR_SYNTAX; return -1; } if ((pPublicKey = X509_get_pubkey(px509Cert)) == NULL) { free(ptr); X509_free(px509Cert); keynote_errno = ERROR_SYNTAX; return -1; } /* RSA-specific */ dc->dec_key = pPublicKey->pkey.rsa; free(ptr); return 0; } /* BINARY keys */ if ((dc->dec_algorithm == KEYNOTE_ALGORITHM_BINARY) && (internalencoding == INTERNAL_ENC_NONE)) { dc->dec_key = calloc(1, sizeof(struct keynote_binary)); if (dc->dec_key == NULL) { keynote_errno = ERROR_MEMORY; return -1; } ((struct keynote_binary *) dc->dec_key)->bn_key = decoded; ((struct keynote_binary *) dc->dec_key)->bn_len = len; return RESULT_TRUE; } /* Add support for more algorithms here */ free(ptr); /* This shouldn't ever be reached really */ keynote_errno = ERROR_SYNTAX; return -1; }
/* * Verify the signature on an assertion; return SIGRESULT_TRUE is * success, SIGRESULT_FALSE otherwise. */ int keynote_sigverify_assertion(struct assertion *as) { int hashtype, enc, intenc, alg = KEYNOTE_ALGORITHM_NONE, hashlen = 0; unsigned char *sig, *decoded = NULL, *ptr; unsigned char res2[20]; SHA_CTX shscontext; MD5_CTX md5context; int len = 0; DSA *dsa; RSA *rsa; if (as->as_signature == NULL || as->as_startofsignature == NULL || as->as_allbutsignature == NULL || as->as_allbutsignature - as->as_startofsignature <= 0) return SIGRESULT_FALSE; alg = keynote_get_sig_algorithm(as->as_signature, &hashtype, &enc, &intenc); if (alg == KEYNOTE_ALGORITHM_NONE) return SIGRESULT_FALSE; /* Check for matching algorithms */ if ((alg != as->as_signeralgorithm) && !((alg == KEYNOTE_ALGORITHM_RSA) && (as->as_signeralgorithm == KEYNOTE_ALGORITHM_X509)) && !((alg == KEYNOTE_ALGORITHM_X509) && (as->as_signeralgorithm == KEYNOTE_ALGORITHM_RSA))) return SIGRESULT_FALSE; sig = strchr(as->as_signature, ':'); /* Move forward to the Encoding. We * are guaranteed to have a ':' * character, since this is a valid * signature */ sig++; switch (hashtype) { case KEYNOTE_HASH_SHA1: hashlen = 20; memset(res2, 0, hashlen); SHA1_Init(&shscontext); SHA1_Update(&shscontext, as->as_startofsignature, as->as_allbutsignature - as->as_startofsignature); SHA1_Update(&shscontext, as->as_signature, (char *) sig - as->as_signature); SHA1_Final(res2, &shscontext); break; case KEYNOTE_HASH_MD5: hashlen = 16; memset(res2, 0, hashlen); MD5_Init(&md5context); MD5_Update(&md5context, as->as_startofsignature, as->as_allbutsignature - as->as_startofsignature); MD5_Update(&md5context, as->as_signature, (char *) sig - as->as_signature); MD5_Final(res2, &md5context); break; case KEYNOTE_HASH_NONE: break; } /* Remove ASCII encoding */ switch (enc) { case ENCODING_NONE: ptr = NULL; break; case ENCODING_HEX: len = strlen(sig) / 2; if (kn_decode_hex(sig, (char **) &decoded) != 0) return -1; ptr = decoded; break; case ENCODING_BASE64: len = strlen(sig); if (len % 4) /* Base64 encoding must be a multiple of 4 */ { keynote_errno = ERROR_SYNTAX; return -1; } len = 3 * (len / 4); decoded = calloc(len, sizeof(unsigned char)); ptr = decoded; if (decoded == NULL) { keynote_errno = ERROR_MEMORY; return -1; } len = kn_decode_base64(sig, decoded, len); if ((len == -1) || (len == 0) || (len == 1)) return -1; break; case ENCODING_NATIVE: if ((decoded = strdup(sig)) == NULL) { keynote_errno = ERROR_MEMORY; return -1; } len = strlen(sig); ptr = decoded; break; default: keynote_errno = ERROR_SYNTAX; return -1; } /* DSA */ if ((alg == KEYNOTE_ALGORITHM_DSA) && (intenc == INTERNAL_ENC_ASN1)) { dsa = (DSA *) as->as_authorizer; if (DSA_verify(0, res2, hashlen, decoded, len, dsa) == 1) { free(ptr); return SIGRESULT_TRUE; } } else /* RSA */ if ((alg == KEYNOTE_ALGORITHM_RSA) && (intenc == INTERNAL_ENC_PKCS1)) { rsa = (RSA *) as->as_authorizer; if (RSA_verify_ASN1_OCTET_STRING(RSA_PKCS1_PADDING, res2, hashlen, decoded, len, rsa) == 1) { free(ptr); return SIGRESULT_TRUE; } } else if ((alg == KEYNOTE_ALGORITHM_X509) && (intenc == INTERNAL_ENC_ASN1)) { /* RSA-specific */ rsa = (RSA *) as->as_authorizer; if (RSA_verify(NID_shaWithRSAEncryption, res2, hashlen, decoded, len, rsa) == 1) { free(ptr); return SIGRESULT_TRUE; } } /* Handle more algorithms here */ free(ptr); return SIGRESULT_FALSE; }
/* * add_variable -- add variable to current session * * if all OK returns 0, otherwise it returns a * negative number that tells you where it got * lost. */ int add_variables(int sessionid, char *pbuf) { char *vp; char *dec_p; // decoded array struct vp_offer *ofp; int n_vars; // retrieved number of variable, value pairs int e_vars; // estimated number according to buffer size // (includes __END__ pair, so // its one item bigger than the actual number int rval; while (*pbuf == ' ' || *pbuf == '\n' || *pbuf == '\t') pbuf++; if ((rval = kn_decode_hex(pbuf, &dec_p)) < 0) { fprintf(stderr, "add_variables: kn_decode_hex(%d), " "returned %d, error %d.\n", strlen(pbuf), rval, keynote_errno); fprintf(stderr, "buffer: <<<%s>>>\n", pbuf); return(-1); } if (dec_p == NULL) { fprintf(stderr, "process_offer: kn_decode_hex returned NULL ???\n"); return(-2); } if ((e_vars = strlen(pbuf)/2) % sizeof(struct vp_offer) != 0) fprintf(stderr, "warning: len (%d) not a multiple of vp_offer" "(%d)\n\tbuf = <<%s>>\n", e_vars, sizeof(struct vp_offer), dec_p); e_vars = e_vars/sizeof(struct vp_offer); // est. number of variables for (ofp = (struct vp_offer *)dec_p, n_vars = 0; strncmp(ENDOFLIST, ofp->o_nam, strlen(ENDOFLIST)) != 0; ofp++, n_vars++) { if (n_vars >= e_vars) { fprintf(stderr, "process_offer: too many variables\n"); break; } printf("\t%s = \"%s\"\n", ofp->o_nam, ofp->o_val); if (kn_add_action(sessionid, ofp->o_nam, ofp->o_val, 0) == -1) { switch (keynote_errno) { case ERROR_SYNTAX: fprintf(stderr, "Invalid name action attribute name " "[%s]\n", ofp->o_nam); break; case ERROR_MEMORY: fprintf(stderr, "Out of mem adding action attribute " "[%s = \"%s\"]\n", ofp->o_nam, ofp->o_val); break; case ERROR_NOTFOUND: fprintf(stderr, "Session %d not found while " "addiing action " "attribute [%s = \"%s\"]\n", sessionid, ofp->o_nam, ofp->o_val); break; default: fprintf(stderr, "Can't happen error %d while adding" "action attribute [%s = \"%s\"]\n", keynote_errno, ofp->o_nam, ofp->o_val); break; } return(-4); } } return(0); }