feeReturn feePubKeyInitFromDERPrivBlob(feePubKey pubKey, unsigned char *keyBlob, size_t keyBlobLen) { pubKeyInst *pkinst = (pubKeyInst *) pubKey; int version; feeReturn frtn; if(pkinst == NULL) { return FR_BadPubKey; } memset(pkinst, 0, sizeof(pubKeyInst)); frtn = feeDERDecodePrivateKey(keyBlob, (unsigned)keyBlobLen, &version, // currently unused &pkinst->cp, &pkinst->privGiant); if(frtn) { return frtn; } /* since this blob only had the private data, infer the remaining fields */ pkinst->plus = new_public(pkinst->cp, CURVE_PLUS); pkinst->minus = new_public(pkinst->cp, CURVE_MINUS); set_priv_key_giant(pkinst->plus, pkinst->privGiant); set_priv_key_giant(pkinst->minus, pkinst->privGiant); return FR_Success; }
/* Caller determines depth from other sources (e.g. AlgId.Params) */ feeReturn feePubKeyInitFromECDSAPubBlob(feePubKey pubKey, const unsigned char *keyBlob, unsigned keyBlobLen, feeDepth depth) { pubKeyInst *pkinst = (pubKeyInst *)pubKey; if(pkinst == NULL) { return FR_BadPubKey; } curveParams *cp = curveParamsForDepth(depth); if(cp == NULL) { return FR_IllegalDepth; } unsigned giantBytes = (cp->q + 7) / 8; unsigned blobSize = 1 + (2 * giantBytes); if(keyBlobLen != blobSize) { dbgLog(("feePubKeyInitFromECDSAPubBlob: bad blobLen\n")); return FR_BadKeyBlob; } if(*keyBlob != 0x04) { dbgLog(("feePubKeyInitFromECDSAPubBlob: bad blob leader\n")); return FR_BadKeyBlob; } pkinst->cp = cp; pkinst->plus = new_public(cp, CURVE_PLUS); deserializeGiant(keyBlob+1, pkinst->plus->x, giantBytes); deserializeGiant(keyBlob+1+giantBytes, pkinst->plus->y, giantBytes); return FR_Success; }
/* * Init feePubKey from curve parameters matching existing oldKey. */ feeReturn feePubKeyInitFromKey(feePubKey pubKey, const unsigned char *privData, unsigned privDataLen, feePubKey oldKey, char hashPrivData) { pubKeyInst *pkinst = (pubKeyInst *) pubKey; pubKeyInst *oldInst = (pubKeyInst *) oldKey; feeReturn frtn; if(oldKey == NULL) { dbgLog(("NULL existing key\n")); return FR_BadPubKey; } pkinst->cp = curveParamsCopy(oldInst->cp); if(pkinst->cp->x1Minus != NULL) { pkinst->minus = new_public(pkinst->cp, CURVE_MINUS); if(pkinst->minus == NULL) { goto abort; } } /* else this curve only usable for ECDSA */ pkinst->plus = new_public(pkinst->cp, CURVE_PLUS); if(pkinst->plus == NULL) { goto abort; } frtn = feeGenPrivate(pkinst, privData, privDataLen, hashPrivData); if(frtn) { return frtn; } set_priv_key_giant(pkinst->plus, pkinst->privGiant); if(pkinst->cp->x1Minus != NULL) { set_priv_key_giant(pkinst->minus, pkinst->privGiant); } return FR_Success; abort: dbgLog(("Bad Existing Public Key\n")); return FR_BadPubKey; }
key new_public_with_key(key old_key, curveParams *cp) { key result; result = new_public(cp, old_key->twist); CKASSERT((old_key->x != NULL) && (old_key->y != NULL)); CKASSERT((result->x != NULL) && (result->y != NULL)); gtog(old_key->x, result->x); gtog(old_key->y, result->y); return result; }
feeReturn feePubKeyInitFromPrivDataDepth(feePubKey pubKey, const unsigned char *privData, unsigned privDataLen, feeDepth depth, char hashPrivData) { pubKeyInst *pkinst = (pubKeyInst *) pubKey; feeReturn frtn; #if ENGINE_127_BITS if(depth != FEE_DEPTH_127_1) { dbgLog(("Illegal Depth\n")); return FR_IllegalDepth; } #endif // ENGINE_127_BITS if(depth > FEE_DEPTH_MAX) { dbgLog(("Illegal Depth\n")); return FR_IllegalDepth; } pkinst->cp = curveParamsForDepth(depth); pkinst->plus = new_public(pkinst->cp, CURVE_PLUS); if(pkinst->cp->x1Minus != NULL) { pkinst->minus = new_public(pkinst->cp, CURVE_MINUS); } /* else only usable for ECDSA */ frtn = feeGenPrivate(pkinst, privData, privDataLen, hashPrivData); if(frtn) { return frtn; } set_priv_key_giant(pkinst->plus, pkinst->privGiant); if(pkinst->cp->x1Minus != NULL) { set_priv_key_giant(pkinst->minus, pkinst->privGiant); } return FR_Success; }
feeReturn feePubKeyInitFromECDSAPrivBlob(feePubKey pubKey, const unsigned char *keyBlob, unsigned keyBlobLen, feeDepth depth) { pubKeyInst *pkinst = (pubKeyInst *)pubKey; if(pkinst == NULL) { return FR_BadPubKey; } curveParams *cp = curveParamsForDepth(depth); if(cp == NULL) { return FR_IllegalDepth; } unsigned giantDigits = cp->basePrime->sign; unsigned giantBytes = (cp->q + 7) / 8; /* * The specified private key can be one byte smaller than the modulus */ if((keyBlobLen > giantBytes) || (keyBlobLen < (giantBytes - 1))) { dbgLog(("feePubKeyInitFromECDSAPrivBlob: bad blobLen\n")); return FR_BadKeyBlob; } pkinst->cp = cp; /* cook up a new private giant */ pkinst->privGiant = newGiant(giantDigits); if(pkinst->privGiant == NULL) { return FR_Memory; } deserializeGiant(keyBlob, pkinst->privGiant, keyBlobLen); /* since this blob only had the private data, infer the remaining fields */ pkinst->plus = new_public(pkinst->cp, CURVE_PLUS); set_priv_key_giant(pkinst->plus, pkinst->privGiant); return FR_Success; }
/* * Init an empty feePubKey from a native blob (non-DER format). */ static feeReturn feePubKeyInitFromKeyBlob(feePubKey pubKey, unsigned char *keyBlob, unsigned keyBlobLen) { pubKeyInst *pkinst = (pubKeyInst *) pubKey; unsigned char *s; // running pointer unsigned sLen; // bytes remaining in *s int magic; unsigned len; // for length of individual components int minVersion; int version; int isPrivate; s = keyBlob; sLen = keyBlobLen; if(sLen < (4 * sizeof(int))) { // magic, version, minVersion, spare /* * Too short for all the ints we need */ dbgLog(("feePublicKey: key blob (1)\n")); return FR_BadKeyBlob; } magic = byteRepToInt(s); s += sizeof(int); sLen -= sizeof(int); switch(magic) { case PUBLIC_KEY_BLOB_MAGIC_PUB: isPrivate = 0; break; case PUBLIC_KEY_BLOB_MAGIC_PRIV: isPrivate = 1; break; default: dbgLog(("feePublicKey: Bad Public Key Magic Number\n")); return FR_BadKeyBlob; } /* * Switch on this for version-specific cases */ version = byteRepToInt(s); s += sizeof(int); sLen -= sizeof(int); minVersion = byteRepToInt(s); s += sizeof(int); sLen -= sizeof(int); if(minVersion > PUBLIC_KEY_BLOB_VERSION) { /* * old code, newer key blob - can't parse */ dbgLog(("feePublicKey: Incompatible Public Key (1)\n")); return FR_BadKeyBlob; } s += sizeof(int); // skip spare sLen -= sizeof(int); pkinst->cp = byteRepToCurveParams(s, sLen, &len); if(pkinst->cp == NULL) { dbgLog(("feePublicKey: Bad Key Blob(2)\n")); return FR_BadKeyBlob; } s += len; sLen -= len; /* * Private key blob: privGiant. * Public Key blob: plusX, minusX, plusY. */ if(isPrivate) { pkinst->privGiant = byteRepToGiant(s, sLen, &len); if(pkinst->privGiant == NULL) { dbgLog(("feePublicKey: Bad Key Blob(3)\n")); return FR_BadKeyBlob; } s += len; sLen -= len; } else { /* this writes x and y */ pkinst->plus = byteRepToKey(s, sLen, CURVE_PLUS, // twist pkinst->cp, &len); if(pkinst->plus == NULL) { dbgLog(("feePublicKey: Bad Key Blob(4)\n")); return FR_BadKeyBlob; } s += len; sLen -= len; /* this only writes x */ pkinst->minus = byteRepToKey(s, sLen, CURVE_MINUS, // twist pkinst->cp, &len); if(pkinst->minus == NULL) { dbgLog(("feePublicKey: Bad Key Blob(5)\n")); return FR_BadKeyBlob; } s += len; sLen -= len; } /* * One more thing: cook up public plusX and minusX for private key * blob case. */ if(isPrivate) { pkinst->plus = new_public(pkinst->cp, CURVE_PLUS); pkinst->minus = new_public(pkinst->cp, CURVE_MINUS); set_priv_key_giant(pkinst->plus, pkinst->privGiant); set_priv_key_giant(pkinst->minus, pkinst->privGiant); } return FR_Success; }