Beispiel #1
0
SECStatus
PKCS11_Derive(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *hKey,
              CK_MECHANISM *pMech, int *dummy)
{
    CK_RV crv;
    CK_OBJECT_HANDLE newKey;
    CK_BBOOL cktrue = CK_TRUE;
    CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
    CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
    CK_ATTRIBUTE keyTemplate[3];
    CK_ATTRIBUTE *attrs = keyTemplate;

    PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass));
    attrs++;
    PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType));
    attrs++;
    PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, 1);
    attrs++;

    crv = NSC_DeriveKey(session, pMech, *hKey, keyTemplate, 3, &newKey);
    if (crv != CKR_OK) {
        printf("Derive Failed CK_RV=0x%x\n", (int)crv);
        return SECFailure;
    }
    return SECSuccess;
}
Beispiel #2
0
Datei: nss.c Projekt: 0w/moai-dev
static int nss_load_key(struct connectdata *conn, int sockindex, char *key_file)
{
#ifdef HAVE_PK11_CREATEGENERICOBJECT
  PK11SlotInfo * slot = NULL;
  CK_ATTRIBUTE *attrs;
  CK_ATTRIBUTE theTemplate[20];
  CK_BBOOL cktrue = CK_TRUE;
  CK_OBJECT_CLASS objClass = CKO_PRIVATE_KEY;
  CK_SLOT_ID slotID;
  char slotname[SLOTSIZE];
  struct ssl_connect_data *sslconn = &conn->ssl[sockindex];

  attrs = theTemplate;

  /* FIXME: grok the various file types */

  slotID = 1; /* hardcoded for now */

  snprintf(slotname, sizeof(slotname), "PEM Token #%ld", slotID);
  slot = PK11_FindSlotByName(slotname);

  if(!slot)
    return 0;

  PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass) ); attrs++;
  PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) ); attrs++;
  PK11_SETATTRS(attrs, CKA_LABEL, (unsigned char *)key_file,
                strlen(key_file)+1); attrs++;

  /* When adding an encrypted key the PKCS#11 will be set as removed */
  sslconn->key = PK11_CreateGenericObject(slot, theTemplate, 3,
                                          PR_FALSE /* isPerm */);
  if(sslconn->key == NULL) {
    PR_SetError(SEC_ERROR_BAD_KEY, 0);
    return 0;
  }

  /* This will force the token to be seen as re-inserted */
  SECMOD_WaitForAnyTokenEvent(mod, 0, 0);
  PK11_IsPresent(slot);

  /* parg is initialized in nss_Init_Tokens() */
  if(PK11_Authenticate(slot, PR_TRUE,
                       conn->data->set.str[STRING_KEY_PASSWD]) != SECSuccess) {

    PK11_FreeSlot(slot);
    return 0;
  }
  PK11_FreeSlot(slot);

  return 1;
#else
  /* If we don't have PK11_CreateGenericObject then we can't load a file-based
   * key.
   */
  (void)conn; /* unused */
  (void)key_file; /* unused */
  return 0;
#endif
}
Beispiel #3
0
static CERTCertificate *load_cert_file(sxc_client_t *sx, const char *file, struct PK11_ctx *ctx) {
    const char *slot_name = "PEM Token #0";
    CK_OBJECT_CLASS obj_class;
    CK_ATTRIBUTE attrs[/* max count of attributes */ 4];
    unsigned attr_cnt = 0;
    CK_BBOOL cktrue = CK_TRUE;
    SECMODModule *mod;
    CERTCertificate *cert = NULL;

    if(!file || !ctx) {
        sxi_seterr(sx, SXE_EARG, "NULL argument");
        return NULL;
    }
    memset(ctx, 0, sizeof(*ctx));

    mod = SECMOD_LoadUserModule("library=libnsspem.so name=PEM", NULL, PR_FALSE);
    if (!mod || !mod->loaded) {
        if (mod)
            SECMOD_DestroyModule(mod);
        sxi_setsyserr(sx, SXE_ECFG, "Failed to load NSS PEM library");
        return NULL;
    }

    sxi_crypto_check_ver(NULL);
    ctx->slot = PK11_FindSlotByName(slot_name);
    if (ctx->slot) {
        obj_class = CKO_CERTIFICATE;
        PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class));
        PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL));
        PK11_SETATTRS(attrs, attr_cnt, CKA_LABEL, (unsigned char *)file,
                      strlen(file) + 1);

        if(CKO_CERTIFICATE == obj_class) {
            CK_BBOOL *pval = &cktrue;
            PK11_SETATTRS(attrs, attr_cnt, CKA_TRUST, pval, sizeof(*pval));
        }

        ctx->obj = PK11_CreateGenericObject(ctx->slot, attrs, attr_cnt, PR_FALSE);
        if (!ctx->obj) {
            sxi_seterr(sx, SXE_ECFG, "Cannot load certificate from '%s': %s, %s",
                       file, PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT),
                       PR_ErrorToName(PR_GetError()));
            return NULL;
        }
        ctx->list = PK11_ListCertsInSlot(ctx->slot);
        if (ctx->list) {
            CERTCertListNode *node = CERT_LIST_HEAD(ctx->list);
            cert = node ? node->cert : NULL;
        }
    } else {
        sxi_seterr(sx, SXE_ECFG, "Failed to initialize NSS PEM token");
        return NULL;
    }

    return cert;
}
Beispiel #4
0
/* Call PK11_CreateGenericObject() with the given obj_class and filename.  If
 * the call succeeds, append the object handle to the list of objects so that
 * the object can be destroyed in Curl_nss_close(). */
static CURLcode nss_create_object(struct ssl_connect_data *ssl,
                                  CK_OBJECT_CLASS obj_class,
                                  const char *filename, bool cacert)
{
  PK11SlotInfo *slot;
  PK11GenericObject *obj;
  CK_BBOOL cktrue = CK_TRUE;
  CK_BBOOL ckfalse = CK_FALSE;
  CK_ATTRIBUTE attrs[/* max count of attributes */ 4];
  int attr_cnt = 0;
  CURLcode err = (cacert)
    ? CURLE_SSL_CACERT_BADFILE
    : CURLE_SSL_CERTPROBLEM;

  const int slot_id = (cacert) ? 0 : 1;
  char *slot_name = aprintf("PEM Token #%d", slot_id);
  if(!slot_name)
    return CURLE_OUT_OF_MEMORY;

  slot = PK11_FindSlotByName(slot_name);
  free(slot_name);
  if(!slot)
    return err;

  PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class));
  PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL));
  PK11_SETATTRS(attrs, attr_cnt, CKA_LABEL, (unsigned char *)filename,
                strlen(filename) + 1);

  if(CKO_CERTIFICATE == obj_class) {
    CK_BBOOL *pval = (cacert) ? (&cktrue) : (&ckfalse);
    PK11_SETATTRS(attrs, attr_cnt, CKA_TRUST, pval, sizeof(*pval));
  }

  obj = PK11_CreateGenericObject(slot, attrs, attr_cnt, PR_FALSE);
  PK11_FreeSlot(slot);
  if(!obj)
    return err;

  if(!Curl_llist_insert_next(ssl->obj_list, ssl->obj_list->tail, obj)) {
    PK11_DestroyGenericObject(obj);
    return CURLE_OUT_OF_MEMORY;
  }

  if(!cacert && CKO_CERTIFICATE == obj_class)
    /* store reference to a client certificate */
    ssl->obj_clicert = obj;

  return CURLE_OK;
}
Beispiel #5
0
/*
 * Return a list of all the CRLs .
 * CRLs are allocated in the list's arena.
 */
SECStatus
PK11_LookupCrls(CERTCrlHeadNode *nodes, int type, void *wincx) {
    pk11TraverseSlot creater;
    CK_ATTRIBUTE theTemplate[2];
    CK_ATTRIBUTE *attrs;
    CK_OBJECT_CLASS certClass = CKO_NETSCAPE_CRL;
    CK_BBOOL isKrl = CK_FALSE;

    attrs = theTemplate;
    PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass)); attrs++;
    if (type != -1) {
	isKrl = (CK_BBOOL) (type == SEC_KRL_TYPE);
        PK11_SETATTRS(attrs, CKA_NETSCAPE_KRL, &isKrl, sizeof(isKrl)); attrs++;
    }

    creater.callback = pk11_CollectCrls;
    creater.callbackArg = (void *) nodes;
    creater.findTemplate = theTemplate;
    creater.templateCount = (attrs - theTemplate);

    return pk11_TraverseAllSlots(PK11_TraverseSlot, &creater, PR_FALSE, wincx);
}
Beispiel #6
0
/*
 * Return a list of CRLs matching specified issuer and type
 * CRLs are not allocated in the list's arena, but rather in their own,
 * arena, so that they can be used individually in the CRL cache .
 * CRLs are always partially decoded for efficiency.
 */
SECStatus pk11_RetrieveCrls(CERTCrlHeadNode *nodes, SECItem* issuer,
                            void *wincx)
{
    pk11TraverseSlot creater;
    CK_ATTRIBUTE theTemplate[2];
    CK_ATTRIBUTE *attrs;
    CK_OBJECT_CLASS crlClass = CKO_NETSCAPE_CRL;
    crlOptions options;

    attrs = theTemplate;
    PK11_SETATTRS(attrs, CKA_CLASS, &crlClass, sizeof(crlClass)); attrs++;

    options.head = nodes;

    /* - do a partial decoding - we don't need to decode the entries while
       fetching
       - don't copy the DER for optimal performance - CRL can be very large
       - have the CRL objects adopt the DER, so SEC_DestroyCrl will free it
       - keep bad CRL objects. The CRL cache is interested in them, for
         security purposes. Bad CRL objects are a sign of something amiss.
    */

    options.decodeOptions = CRL_DECODE_SKIP_ENTRIES | CRL_DECODE_DONT_COPY_DER |
                            CRL_DECODE_ADOPT_HEAP_DER | CRL_DECODE_KEEP_BAD_CRL;
    if (issuer)
    {
        PK11_SETATTRS(attrs, CKA_SUBJECT, issuer->data, issuer->len); attrs++;
    }

    creater.callback = pk11_RetrieveCrlsCallback;
    creater.callbackArg = (void *) &options;
    creater.findTemplate = theTemplate;
    creater.templateCount = (attrs - theTemplate);

    return pk11_TraverseAllSlots(PK11_TraverseSlot, &creater, PR_FALSE, wincx);
}
Beispiel #7
0
PRBool
pk11_HandleTrustObject(PK11SlotInfo *slot, CERTCertificate *cert, CERTCertTrust *trust)
{
  PRArenaPool *arena;

  CK_ATTRIBUTE tobjTemplate[] = {
    { CKA_CLASS, NULL, 0 },
    { CKA_CERT_SHA1_HASH, NULL, 0 },
  };

  CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST;
  CK_OBJECT_HANDLE tobjID;
  unsigned char sha1_hash[SHA1_LENGTH];

  CK_TRUST serverAuth, codeSigning, emailProtection, clientAuth;

  PK11_HashBuf(SEC_OID_SHA1, sha1_hash, cert->derCert.data, cert->derCert.len);

  PK11_SETATTRS(&tobjTemplate[0], CKA_CLASS, &tobjc, sizeof(tobjc));
  PK11_SETATTRS(&tobjTemplate[1], CKA_CERT_SHA1_HASH, sha1_hash, 
                SHA1_LENGTH);

  tobjID = pk11_FindObjectByTemplate(slot, tobjTemplate, 
                                     sizeof(tobjTemplate)/sizeof(tobjTemplate[0]));
  if( CK_INVALID_HANDLE == tobjID ) {
    return PR_FALSE;
  }

  arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  if( NULL == arena ) return PR_FALSE;

  /* Unfortunately, it seems that PK11_GetAttributes doesn't deal
   * well with nonexistent attributes.  I guess we have to check 
   * the trust info fields one at a time.
   */

  /* We could verify CKA_CERT_HASH here */

  /* We could verify CKA_EXPIRES here */


  /* "Purpose" trust information */
  serverAuth = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_SERVER_AUTH);
  clientAuth = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CLIENT_AUTH);
  codeSigning = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CODE_SIGNING);
  emailProtection = pk11_GetTrustField(slot, arena, tobjID, 
						CKA_TRUST_EMAIL_PROTECTION);
  /* Here's where the fun logic happens.  We have to map back from the 
   * key usage, extended key usage, purpose, and possibly other trust values 
   * into the old trust-flags bits.  */

  /* First implementation: keep it simple for testing.  We can study what other
   * mappings would be appropriate and add them later.. fgmr 20000724 */

  if ( serverAuth ==  CKT_NSS_TRUSTED ) {
    trust->sslFlags |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED;
  }

  if ( serverAuth == CKT_NSS_TRUSTED_DELEGATOR ) {
    trust->sslFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | 
							CERTDB_NS_TRUSTED_CA;
  }
  if ( clientAuth == CKT_NSS_TRUSTED_DELEGATOR ) {
    trust->sslFlags |=  CERTDB_TRUSTED_CLIENT_CA ;
  }

  if ( emailProtection == CKT_NSS_TRUSTED ) {
    trust->emailFlags |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED;
  }

  if ( emailProtection == CKT_NSS_TRUSTED_DELEGATOR ) {
    trust->emailFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA;
  }

  if( codeSigning == CKT_NSS_TRUSTED ) {
    trust->objectSigningFlags |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED;
  }

  if( codeSigning == CKT_NSS_TRUSTED_DELEGATOR ) {
    trust->objectSigningFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA;
  }

  /* There's certainly a lot more logic that can go here.. */

  PORT_FreeArena(arena, PR_FALSE);

  return PR_TRUE;
}
Beispiel #8
0
SECStatus
PK11_SaveSMimeProfile(PK11SlotInfo *slot, char *emailAddr, SECItem *derSubj,
				 SECItem *emailProfile,  SECItem *profileTime)
{
    CK_OBJECT_CLASS smimeClass = CKO_NETSCAPE_SMIME;
    CK_BBOOL ck_true = CK_TRUE;
    CK_ATTRIBUTE theTemplate[] = {
	{ CKA_CLASS, NULL, 0 },
	{ CKA_TOKEN, NULL, 0 },
	{ CKA_SUBJECT, NULL, 0 },
	{ CKA_NETSCAPE_EMAIL, NULL, 0 },
	{ CKA_NETSCAPE_SMIME_TIMESTAMP, NULL, 0 },
	{ CKA_VALUE, NULL, 0 }
    };
    /* if you change the array, change the variable below as well */
    int realSize = 0;
    CK_OBJECT_HANDLE smimeh = CK_INVALID_HANDLE;
    CK_ATTRIBUTE *attrs = theTemplate;
    CK_SESSION_HANDLE rwsession;
    PK11SlotInfo *free_slot = NULL;
    CK_RV crv;
#ifdef DEBUG
    int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
#endif

    PK11_SETATTRS(attrs, CKA_CLASS, &smimeClass, sizeof(smimeClass)); attrs++;
    PK11_SETATTRS(attrs, CKA_TOKEN, &ck_true, sizeof(ck_true)); attrs++;
    PK11_SETATTRS(attrs, CKA_SUBJECT, derSubj->data, derSubj->len); attrs++;
    PK11_SETATTRS(attrs, CKA_NETSCAPE_EMAIL, 
				emailAddr, PORT_Strlen(emailAddr)+1); attrs++;
    if (profileTime) {
	PK11_SETATTRS(attrs, CKA_NETSCAPE_SMIME_TIMESTAMP, profileTime->data,
	                                            profileTime->len); attrs++;
	PK11_SETATTRS(attrs, CKA_VALUE,emailProfile->data,
	                                            emailProfile->len); attrs++;
    }
    realSize = attrs - theTemplate;
    PORT_Assert (realSize <= tsize);

    if (slot == NULL) {
	free_slot = slot = PK11_GetInternalKeySlot();
	/* we need to free the key slot in the end!!! */
    }

    rwsession = PK11_GetRWSession(slot);
    if (rwsession == CK_INVALID_SESSION) {
	PORT_SetError(SEC_ERROR_READ_ONLY);
	if (free_slot) {
	    PK11_FreeSlot(free_slot);
	}
	return SECFailure;
    }

    crv = PK11_GETTAB(slot)->
                        C_CreateObject(rwsession,theTemplate,realSize,&smimeh);
    if (crv != CKR_OK) {
        PORT_SetError( PK11_MapError(crv) );
    }

    PK11_RestoreROSession(slot,rwsession);

    if (free_slot) {
	PK11_FreeSlot(free_slot);
    }
    return SECSuccess;
}
Beispiel #9
0
/*
 * return the certificate associated with a derCert 
 */
SECItem *
PK11_FindSMimeProfile(PK11SlotInfo **slot, char *emailAddr,
				 SECItem *name, SECItem **profileTime)
{
    CK_OBJECT_CLASS smimeClass = CKO_NETSCAPE_SMIME;
    CK_ATTRIBUTE theTemplate[] = {
	{ CKA_SUBJECT, NULL, 0 },
	{ CKA_CLASS, NULL, 0 },
	{ CKA_NETSCAPE_EMAIL, NULL, 0 },
    };
    CK_ATTRIBUTE smimeData[] =  {
	{ CKA_SUBJECT, NULL, 0 },
	{ CKA_VALUE, NULL, 0 },
    };
    /* if you change the array, change the variable below as well */
    int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
    CK_OBJECT_HANDLE smimeh = CK_INVALID_HANDLE;
    CK_ATTRIBUTE *attrs = theTemplate;
    CK_RV crv;
    SECItem *emailProfile = NULL;

    if (!emailAddr || !emailAddr[0]) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return NULL;
    }

    PK11_SETATTRS(attrs, CKA_SUBJECT, name->data, name->len); attrs++;
    PK11_SETATTRS(attrs, CKA_CLASS, &smimeClass, sizeof(smimeClass)); attrs++;
    PK11_SETATTRS(attrs, CKA_NETSCAPE_EMAIL, emailAddr, strlen(emailAddr)); 
								    attrs++;

    if (*slot) {
    	smimeh = pk11_FindObjectByTemplate(*slot,theTemplate,tsize);
    } else {
	PK11SlotList *list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,
							PR_FALSE,PR_TRUE,NULL);
	PK11SlotListElement *le;

	if (!list) {
	    return NULL;
	}
	/* loop through all the slots */
	for (le = list->head; le; le = le->next) {
	    smimeh = pk11_FindObjectByTemplate(le->slot,theTemplate,tsize);
	    if (smimeh != CK_INVALID_HANDLE) {
		*slot = PK11_ReferenceSlot(le->slot);
		break;
	    }
	}
	PK11_FreeSlotList(list);
    }
    
    if (smimeh == CK_INVALID_HANDLE) {
	PORT_SetError(SEC_ERROR_NO_KRL);
	return NULL;
    }

    if (profileTime) {
    	PK11_SETATTRS(smimeData, CKA_NETSCAPE_SMIME_TIMESTAMP, NULL, 0);
    } 
    
    crv = PK11_GetAttributes(NULL,*slot,smimeh,smimeData,2);
    if (crv != CKR_OK) {
	PORT_SetError(PK11_MapError (crv));
	goto loser;
    }

    if (!profileTime) {
	SECItem profileSubject;

	profileSubject.data = (unsigned char*) smimeData[0].pValue;
	profileSubject.len = smimeData[0].ulValueLen;
	if (!SECITEM_ItemsAreEqual(&profileSubject,name)) {
	    goto loser;
	}
    }

    emailProfile = (SECItem *)PORT_ZAlloc(sizeof(SECItem));    
    if (emailProfile == NULL) {
	goto loser;
    }

    emailProfile->data = (unsigned char*) smimeData[1].pValue;
    emailProfile->len = smimeData[1].ulValueLen;

    if (profileTime) {
	*profileTime = (SECItem *)PORT_ZAlloc(sizeof(SECItem));    
	if (*profileTime) {
	    (*profileTime)->data = (unsigned char*) smimeData[0].pValue;
	    (*profileTime)->len = smimeData[0].ulValueLen;
	}
    }

loser:
    if (emailProfile == NULL) {
	if (smimeData[1].pValue) {
	    PORT_Free(smimeData[1].pValue);
	}
    }
    if (profileTime == NULL || *profileTime == NULL) {
	if (smimeData[0].pValue) {
	    PORT_Free(smimeData[0].pValue);
	}
    }
    return emailProfile;
}
Beispiel #10
0
Datei: nss.c Projekt: 0w/moai-dev
static int nss_load_cert(struct ssl_connect_data *ssl,
                         const char *filename, PRBool cacert)
{
#ifdef HAVE_PK11_CREATEGENERICOBJECT
  CK_SLOT_ID slotID;
  PK11SlotInfo * slot = NULL;
  CK_ATTRIBUTE *attrs;
  CK_ATTRIBUTE theTemplate[20];
  CK_BBOOL cktrue = CK_TRUE;
  CK_BBOOL ckfalse = CK_FALSE;
  CK_OBJECT_CLASS objClass = CKO_CERTIFICATE;
  char slotname[SLOTSIZE];
#endif
  CERTCertificate *cert;
  char *nickname = NULL;
  char *n = NULL;

  /* If there is no slash in the filename it is assumed to be a regular
   * NSS nickname.
   */
  if(is_file(filename)) {
    n = strrchr(filename, '/');
    if(n)
      n++;
    if(!mod)
      return 1;
  }
  else {
    /* A nickname from the NSS internal database */
    if(cacert)
      return 0; /* You can't specify an NSS CA nickname this way */
    nickname = strdup(filename);
    if(!nickname)
      return 0;
    goto done;
  }

#ifdef HAVE_PK11_CREATEGENERICOBJECT
  attrs = theTemplate;

  /* All CA and trust objects go into slot 0. Other slots are used
   * for storing certificates. With each new user certificate we increment
   * the slot count. We only support 1 user certificate right now.
   */
  if(cacert)
    slotID = 0;
  else
    slotID = 1;

  snprintf(slotname, SLOTSIZE, "PEM Token #%ld", slotID);

  nickname = aprintf("PEM Token #%ld:%s", slotID, n);
  if(!nickname)
    return 0;

  slot = PK11_FindSlotByName(slotname);

  if(!slot) {
    free(nickname);
    return 0;
  }

  PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass) );
  attrs++;
  PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) );
  attrs++;
  PK11_SETATTRS(attrs, CKA_LABEL, (unsigned char *)filename,
                strlen(filename)+1);
  attrs++;
  if(cacert) {
    PK11_SETATTRS(attrs, CKA_TRUST, &cktrue, sizeof(CK_BBOOL) );
  }
  else {
    PK11_SETATTRS(attrs, CKA_TRUST, &ckfalse, sizeof(CK_BBOOL) );
  }
  attrs++;

  /* This load the certificate in our PEM module into the appropriate
   * slot.
   */
  ssl->cacert[slotID] = PK11_CreateGenericObject(slot, theTemplate, 4,
                                         PR_FALSE /* isPerm */);

  PK11_FreeSlot(slot);

  if(ssl->cacert[slotID] == NULL) {
    free(nickname);
    return 0;
  }
#else
  /* We don't have PK11_CreateGenericObject but a file-based cert was passed
   * in. We need to fail.
   */
  return 0;
#endif

done:
  /* Double-check that the certificate or nickname requested exists in
   * either the token or the NSS certificate database.
   */
  if(!cacert) {
    cert = PK11_FindCertFromNickname((char *)nickname, NULL);

    /* An invalid nickname was passed in */
    if(cert == NULL) {
      free(nickname);
      PR_SetError(SEC_ERROR_UNKNOWN_CERT, 0);
      return 0;
    }

    CERT_DestroyCertificate(cert);
  }

  free(nickname);

  return 1;
}
Beispiel #11
0
SECStatus
PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk, 
	SECItem *nickname, SECItem *publicValue, PRBool isPerm, 
	PRBool isPrivate, unsigned int keyUsage, SECKEYPrivateKey **privk,
	void *wincx) 
{
    CK_BBOOL cktrue = CK_TRUE;
    CK_BBOOL ckfalse = CK_FALSE;
    CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
    CK_KEY_TYPE keyType = CKK_RSA;
    CK_OBJECT_HANDLE objectID;
    CK_ATTRIBUTE theTemplate[20];
    int templateCount = 0;
    SECStatus rv = SECFailure;
    PRArenaPool *arena;
    CK_ATTRIBUTE *attrs;
    CK_ATTRIBUTE *signedattr = NULL;
    int signedcount = 0;
    CK_ATTRIBUTE *ap;
    SECItem *ck_id = NULL;

    arena = PORT_NewArena(2048);
    if(!arena) {
	return SECFailure;
    }

    attrs = theTemplate;


    PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass) ); attrs++;
    PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType) ); attrs++;
    PK11_SETATTRS(attrs, CKA_TOKEN, isPerm ? &cktrue : &ckfalse, 
						sizeof(CK_BBOOL) ); attrs++;
    PK11_SETATTRS(attrs, CKA_SENSITIVE, isPrivate ? &cktrue : &ckfalse, 
						sizeof(CK_BBOOL) ); attrs++;
    PK11_SETATTRS(attrs, CKA_PRIVATE, isPrivate ? &cktrue : &ckfalse,
						 sizeof(CK_BBOOL) ); attrs++;

    switch (lpk->keyType) {
    case rsaKey:
	    keyType = CKK_RSA;
	    PK11_SETATTRS(attrs, CKA_UNWRAP, (keyUsage & KU_KEY_ENCIPHERMENT) ?
				&cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++;
	    PK11_SETATTRS(attrs, CKA_DECRYPT, (keyUsage & KU_DATA_ENCIPHERMENT) ?
				&cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++;
	    PK11_SETATTRS(attrs, CKA_SIGN, (keyUsage & KU_DIGITAL_SIGNATURE) ? 
				&cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++;
	    PK11_SETATTRS(attrs, CKA_SIGN_RECOVER, 
				(keyUsage & KU_DIGITAL_SIGNATURE) ? 
				&cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++;
	    ck_id = PK11_MakeIDFromPubKey(&lpk->u.rsa.modulus);
	    if (ck_id == NULL) {
		goto loser;
	    }
	    PK11_SETATTRS(attrs, CKA_ID, ck_id->data,ck_id->len); attrs++;
	    if (nickname) {
		PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len); attrs++; 
	    } 
	    signedattr = attrs;
	    PK11_SETATTRS(attrs, CKA_MODULUS, lpk->u.rsa.modulus.data,
						lpk->u.rsa.modulus.len); attrs++;
	    PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, 
	     			lpk->u.rsa.publicExponent.data,
				lpk->u.rsa.publicExponent.len); attrs++;
	    PK11_SETATTRS(attrs, CKA_PRIVATE_EXPONENT, 
	     			lpk->u.rsa.privateExponent.data,
				lpk->u.rsa.privateExponent.len); attrs++;
	    PK11_SETATTRS(attrs, CKA_PRIME_1, 
	     			lpk->u.rsa.prime1.data,
				lpk->u.rsa.prime1.len); attrs++;
	    PK11_SETATTRS(attrs, CKA_PRIME_2, 
	     			lpk->u.rsa.prime2.data,
				lpk->u.rsa.prime2.len); attrs++;
	    PK11_SETATTRS(attrs, CKA_EXPONENT_1, 
	     			lpk->u.rsa.exponent1.data,
				lpk->u.rsa.exponent1.len); attrs++;
	    PK11_SETATTRS(attrs, CKA_EXPONENT_2, 
	     			lpk->u.rsa.exponent2.data,
				lpk->u.rsa.exponent2.len); attrs++;
	    PK11_SETATTRS(attrs, CKA_COEFFICIENT, 
	     			lpk->u.rsa.coefficient.data,
				lpk->u.rsa.coefficient.len); attrs++;
	    break;
    case dsaKey:
	    keyType = CKK_DSA;
	    /* To make our intenal PKCS #11 module work correctly with 
	     * our database, we need to pass in the public key value for 
	     * this dsa key. We have a netscape only CKA_ value to do this.
	     * Only send it to internal slots */
	    if( publicValue == NULL ) {
		goto loser;
	    }
	    if (PK11_IsInternal(slot)) {
	        PK11_SETATTRS(attrs, CKA_NETSCAPE_DB,
				publicValue->data, publicValue->len); attrs++;
	    }
	    PK11_SETATTRS(attrs, CKA_SIGN, &cktrue, sizeof(CK_BBOOL)); attrs++;
	    PK11_SETATTRS(attrs, CKA_SIGN_RECOVER, &cktrue, sizeof(CK_BBOOL)); attrs++;
	    if(nickname) {
		PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
		attrs++; 
	    } 
	    ck_id = PK11_MakeIDFromPubKey(publicValue);
	    if (ck_id == NULL) {
		goto loser;
	    }
	    PK11_SETATTRS(attrs, CKA_ID, ck_id->data,ck_id->len); attrs++;
	    signedattr = attrs;
	    PK11_SETATTRS(attrs, CKA_PRIME,    lpk->u.dsa.params.prime.data,
				lpk->u.dsa.params.prime.len); attrs++;
	    PK11_SETATTRS(attrs,CKA_SUBPRIME,lpk->u.dsa.params.subPrime.data,
				lpk->u.dsa.params.subPrime.len); attrs++;
	    PK11_SETATTRS(attrs, CKA_BASE,  lpk->u.dsa.params.base.data,
					lpk->u.dsa.params.base.len); attrs++;
	    PK11_SETATTRS(attrs, CKA_VALUE,    lpk->u.dsa.privateValue.data, 
					lpk->u.dsa.privateValue.len); attrs++;
	    break;
     case dhKey:
	    keyType = CKK_DH;
	    /* To make our intenal PKCS #11 module work correctly with 
	     * our database, we need to pass in the public key value for 
	     * this dh key. We have a netscape only CKA_ value to do this.
	     * Only send it to internal slots */
	    if (PK11_IsInternal(slot)) {
	        PK11_SETATTRS(attrs, CKA_NETSCAPE_DB,
				publicValue->data, publicValue->len); attrs++;
	    }
	    PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL)); attrs++;
	    if(nickname) {
		PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
		attrs++; 
	    } 
	    ck_id = PK11_MakeIDFromPubKey(publicValue);
	    if (ck_id == NULL) {
		goto loser;
	    }
	    PK11_SETATTRS(attrs, CKA_ID, ck_id->data,ck_id->len); attrs++;
	    signedattr = attrs;
	    PK11_SETATTRS(attrs, CKA_PRIME,    lpk->u.dh.prime.data,
				lpk->u.dh.prime.len); attrs++;
	    PK11_SETATTRS(attrs, CKA_BASE,  lpk->u.dh.base.data,
					lpk->u.dh.base.len); attrs++;
	    PK11_SETATTRS(attrs, CKA_VALUE,    lpk->u.dh.privateValue.data, 
					lpk->u.dh.privateValue.len); attrs++;
	    break;
	/* what about fortezza??? */
    default:
	    PORT_SetError(SEC_ERROR_BAD_KEY);
	    goto loser;
    }
    templateCount = attrs - theTemplate;
    PORT_Assert(templateCount <= sizeof(theTemplate)/sizeof(CK_ATTRIBUTE));
    PORT_Assert(signedattr != NULL);
    signedcount = attrs - signedattr;

    for (ap=signedattr; signedcount; ap++, signedcount--) {
	pk11_SignedToUnsigned(ap);
    }

    rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION,
			theTemplate, templateCount, isPerm, &objectID);

    /* create and return a SECKEYPrivateKey */
    if( rv == SECSuccess && privk != NULL) {
	*privk = PK11_MakePrivKey(slot, lpk->keyType, !isPerm, objectID, wincx);
	if( *privk == NULL ) {
	    rv = SECFailure;
	}
    }
loser:
    if (ck_id) {
	SECITEM_ZfreeItem(ck_id, PR_TRUE);
    }
    return rv;
}
Beispiel #12
0
static int nss_load_key(struct connectdata *conn, char *key_file)
{
#ifdef HAVE_PK11_CREATEGENERICOBJECT
  PK11SlotInfo * slot = NULL;
  PK11GenericObject *rv;
  CK_ATTRIBUTE *attrs;
  CK_ATTRIBUTE theTemplate[20];
  CK_BBOOL cktrue = CK_TRUE;
  CK_OBJECT_CLASS objClass = CKO_PRIVATE_KEY;
  CK_SLOT_ID slotID;
  char *slotname = NULL;
  pphrase_arg_t *parg = NULL;

  attrs = theTemplate;

  /* FIXME: grok the various file types */

  slotID = 1; /* hardcoded for now */

  slotname = (char *)malloc(SLOTSIZE);
  snprintf(slotname, SLOTSIZE, "PEM Token #%ld", slotID);

  slot = PK11_FindSlotByName(slotname);
  free(slotname);

  if(!slot)
    return 0;

  PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass) ); attrs++;
  PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) ); attrs++;
  PK11_SETATTRS(attrs, CKA_LABEL, (unsigned char *)key_file,
                strlen(key_file)+1); attrs++;

  /* When adding an encrypted key the PKCS#11 will be set as removed */
  rv = PK11_CreateGenericObject(slot, theTemplate, 3, PR_FALSE /* isPerm */);
  if(rv == NULL) {
    PR_SetError(SEC_ERROR_BAD_KEY, 0);
    return 0;
  }

  /* This will force the token to be seen as re-inserted */
  SECMOD_WaitForAnyTokenEvent(mod, 0, 0);
  PK11_IsPresent(slot);

  parg = (pphrase_arg_t *) malloc(sizeof(*parg));
  parg->retryCount = 0;
  parg->data = conn->data;
  /* parg is initialized in nss_Init_Tokens() */
  if(PK11_Authenticate(slot, PR_TRUE, parg) != SECSuccess) {
    free(parg);
    return 0;
  }
  free(parg);

  return 1;
#else
  /* If we don't have PK11_CreateGenericObject then we can't load a file-based
   * key.
   */
  (void)conn; /* unused */
  (void)key_file; /* unused */
  return 0;
#endif
}